Compare commits

..

122 Commits

Author SHA1 Message Date
4844eea0ab add convenience function g.Client for ghttp.Client 2020-03-29 09:52:37 +08:00
8ecd62d3de add example for package gres 2020-03-28 21:32:29 +08:00
4c610b4f58 improve session storage file for ghttp.Server 2020-03-28 20:02:57 +08:00
1932c4ec44 Merge pull request #575 from wenzi1/master
Fix the bug of MSSQL paging
2020-03-28 19:59:31 +08:00
bd2e51ddca improve unit testing case for package glog 2020-03-28 00:47:34 +08:00
ddcb7121c1 improve temporary path producing from gfile.Join to gfile.TempDir 2020-03-28 00:41:12 +08:00
f1f575fd5c improve package gins/gfile/intlog 2020-03-28 00:37:23 +08:00
99adb7cdc4 comment update 2020-03-26 23:48:21 +08:00
6b7ea97777 improve quote handling of table string for package gdb; improve rotation feature for package glog 2020-03-26 22:25:43 +08:00
495b5758ec improve quote handling of table string for package gdb; improve rotation feature for package glog 2020-03-26 22:22:27 +08:00
ba56eb87b1 improve rotation feature for package glog 2020-03-26 20:58:57 +08:00
4258a3bbc9 improve StrToSize function for package gfile 2020-03-26 15:54:57 +08:00
4912331ddc improve mtime feature for gfile; improve rotation feature for glog 2020-03-26 09:29:36 +08:00
e87b7ecf5d improve unit testing case for package gfpool 2020-03-26 08:52:50 +08:00
23bce7bde6 reduce the goroutine count for unit testing cases of package gfpool/glog 2020-03-25 23:49:33 +08:00
926b664615 improve package garray for crossing border handling; improve rotation feature for package glog 2020-03-25 23:36:56 +08:00
fa8257c85b improve ghttp.Client 2020-03-25 17:13:05 +08:00
abb9c88c23 improve ghttp.Client 2020-03-25 15:17:18 +08:00
f89976cad5 improve ghttp.Client 2020-03-25 15:09:13 +08:00
0389778725 improve package glog for file lock 2020-03-25 00:03:52 +08:00
3c36285126 improve Model.Data function for package gdb 2020-03-24 20:58:11 +08:00
75054ee109 fix issue in rebinding feature for grou router of ghttp.Server 2020-03-24 19:48:10 +08:00
8447b1a42b add function LevelStr/StackWithFilter functions for package glog 2020-03-24 00:05:11 +08:00
e5265a1c46 add level string feature for package glog 2020-03-23 22:40:44 +08:00
6e8ef8d0b0 add level string feature for package glog 2020-03-23 22:36:06 +08:00
75c081afc9 fix issue of char '/' in URL.Path handling of ghttp.Server 2020-03-23 20:57:34 +08:00
060fd9eaba improve comment for package gdb 2020-03-23 20:44:20 +08:00
63e5a60344 improve package gdb 2020-03-22 23:26:15 +08:00
75dc1d82c1 example names change 2020-03-22 12:49:46 +08:00
a5e048eb5f example name changes 2020-03-22 12:34:12 +08:00
65bc1d5eb8 comment update for package gjson 2020-03-22 09:24:45 +08:00
bfa64705b5 update comment for package gsession 2020-03-22 00:15:59 +08:00
17aea8d7d4 improve unit testing cases by changing creating testdata path using gdebug.TestdataPath function 2020-03-21 23:47:33 +08:00
a6a01fd7f2 improve template cache for ParseContent function of package gview 2020-03-21 23:42:34 +08:00
41a9e91b4c improve example for package gpage 2020-03-21 23:13:31 +08:00
e2c1e11f95 improve package gjson 2020-03-21 21:32:02 +08:00
c2966817ce improve function gdebug.TestDataPath and update all usage codes 2020-03-21 19:41:05 +08:00
16958413bb improve autoencode feature for package gview 2020-03-21 19:31:58 +08:00
c0a0913d4b add more unit testing case for template feature of ghttp.Server 2020-03-21 13:45:33 +08:00
6d47810782 improve context feature for ghttp.Request; improve comment for package gjson 2020-03-21 13:32:43 +08:00
7a9ea2e546 improve context feature for ghttp.Request 2020-03-20 23:22:32 +08:00
7881b2dee4 improve unit testing cases 2020-03-20 22:34:56 +08:00
5f223ef049 Merge pull request #4 from gogf/master
update
2020-03-20 10:06:50 +08:00
e57942b374 improve unit testing cases 2020-03-20 08:56:17 +08:00
f18e6f078c improve unit testing cases 2020-03-20 08:49:40 +08:00
f667cbc2a2 Fix the bug of MSSQL paging 2020-03-20 00:33:20 +08:00
07e65c14a9 improve unit testing cases 2020-03-19 23:53:03 +08:00
0b6d04485e improve unit testing cases 2020-03-19 22:56:12 +08:00
36401a063d improve gutil.Dump, improve sqlite file searching when opening db file 2020-03-19 13:38:42 +08:00
849e7370d1 improve gutil.Dump, improve sqlite file searching when opening db file 2020-03-19 11:37:31 +08:00
f01dca0895 version updates 2020-03-17 22:36:05 +08:00
55137b2aa3 README, DONATOR updates 2020-03-17 22:35:09 +08:00
22540921b3 improve codes typing for package package gvalid 2020-03-17 22:23:29 +08:00
6174097a07 Merge pull request #3 from gogf/master
update
2020-03-17 22:11:51 +08:00
52de11b1fe Merge pull request #564 from arieslee/master 2020-03-17 22:08:31 +08:00
5a646179ad fix issue in limit...offset statement of postgresql for packagegdb 2020-03-17 21:38:49 +08:00
33ae93e050 improve CORS feature for ghttp.Server 2020-03-17 17:46:43 +08:00
f3d859159d improve router group for duplicated router registering for package ghttp.Server 2020-03-17 14:48:52 +08:00
4fb01e68f7 移除字符串ip地址与Long类型互转的方法,修改中文长度校验的方法 2020-03-17 14:26:36 +08:00
2812a247aa 添加验证中英文混合字符串长度的判断规则,按utf8计算,一个中文算一个字符,cn-length,cn-min-length,cn-max-length 2020-03-17 11:19:43 +08:00
2b46e765c4 change function time.Duration.Milliseconds to time.Duration.Nanoseconds for compatibility of Golang version < 1.13 2020-03-16 23:03:37 +08:00
c7f911cae2 change function time.Duration.Milliseconds to time.Duration.Nanoseconds for compatibility of Golang version < 1.13 2020-03-16 23:03:35 +08:00
9f0548c03d improve testdata directory retrieving for unit testing cases 2020-03-16 22:47:39 +08:00
c578df06a3 fix issue in unit testing case of package gfile 2020-03-16 20:51:19 +08:00
8ed3cf9c97 fix issue in unit testing case of package gcdg 2020-03-16 20:46:03 +08:00
2438f565e9 添加字符串ip地址与Long类型互转的方法 2020-03-16 11:18:06 +08:00
8230c72ec6 improve file uploading feature for ghttp.Request 2020-03-15 20:11:38 +08:00
d716037caa improve package gcfg adding default configuration file searching for instance 2020-03-15 19:56:07 +08:00
855a4ddb2c add file rotation feature for package glog; improve gpool/gfpool; fix issue in gfile.MTimeMillisecond 2020-03-15 19:32:29 +08:00
74be9fac18 add file rotation feature for package glog; improve gpool/gfpool; fix issue in gfile.MTimeMillisecond 2020-03-15 19:32:26 +08:00
e9fba5a166 readme updates 2020-03-14 17:15:25 +08:00
0a92df691b improve package gpool/gfpool; donator updates 2020-03-14 17:12:44 +08:00
e513cd10ed add Lock* functions for gdb.Model and improve Data/Where functions for gdb.Model 2020-03-13 17:21:30 +08:00
b702d98700 version updates 2020-03-12 10:05:38 +08:00
99f1d9d0ed improve package gudp 2020-03-11 23:59:43 +08:00
707b08c585 improve package gudp 2020-03-11 23:56:58 +08:00
f44c19868c improve package gudp 2020-03-11 23:54:35 +08:00
13ab139afc add more unit testing case for package gdb 2020-03-11 23:24:19 +08:00
cacb2f142b Merge pull request #548 from wenzi1/master
add Tables and TableFields method for sqlite
2020-03-11 23:18:59 +08:00
11f0317e92 add Array feature for package gdb 2020-03-11 23:17:41 +08:00
9a667c8803 add Tables and TableFields method for sqlite 2020-03-11 22:45:38 +08:00
c1cce17934 add unit testing cases for gudp 2020-03-11 16:08:17 +08:00
5a92d7de0d fix issue in router group registering for controller 2020-03-11 15:51:24 +08:00
53bf378868 Merge pull request #550 from fulltimelove/master 2020-03-11 15:07:30 +08:00
cd7c45c00c improve default connection pool configuration for gredis 2020-03-11 14:35:23 +08:00
f13a5ad82e 分组路由对象绑定时支持多方法绑定 2020-03-11 10:10:00 +08:00
2e9be609c8 fix issue in unit testing of gins 2020-03-11 09:22:13 +08:00
2f2f6e1ffe add Tables and TableFields method 2020-03-11 00:29:25 +08:00
f3bd2b67f7 change attribute Context to context.Context for ghttp.Request 2020-03-10 20:45:22 +08:00
645cecdffb improve template view instance initialization for instance of ghttp.Server 2020-03-10 20:13:36 +08:00
22e9965629 improve template view instance initialization for instance of ghttp.Server 2020-03-10 08:57:37 +08:00
24ea9f9245 Merge pull request #2 from gogf/master
update
2020-03-09 23:35:59 +08:00
9dbde6e8f1 change function HandleSqlBeforeExec to HandleSqlBeforeCommit for package gdb 2020-03-09 22:00:01 +08:00
fe0b34544d fix missing of pgsql driver support for package gdb 2020-03-09 21:56:53 +08:00
5e489d59b4 improve HandleSqlBeforeExec function for package gdb 2020-03-09 21:53:58 +08:00
61f49574a9 fix issue in unit testing case for gparser 2020-03-09 20:56:10 +08:00
2fabcb62a8 remove binary from git 2020-03-09 19:48:51 +08:00
3bc3b652c1 improve unit testing case for gjson 2020-03-09 09:00:38 +08:00
042a6f12f5 add map conversion support for result of HGetAll for package gredis 2020-03-08 23:16:06 +08:00
5acce82e63 add slice support for gconv.Map 2020-03-08 23:09:37 +08:00
4732bf46ad add Context map for internal context workflow parameter exchanges for ghttp.Request 2020-03-08 22:53:20 +08:00
5bed5a1532 improve unit testing case for driver feature og package gdb 2020-03-08 12:18:07 +08:00
5b7576430f improve unit testing case for driver feature og package gdb 2020-03-08 12:16:44 +08:00
356f4cd701 improve unit testing case for driver feature og package gdb 2020-03-08 12:04:24 +08:00
c444630d1e add workaround for package gdb for json infinite loop bug of Golang version < v1.14 2020-03-08 11:56:19 +08:00
8e40cded42 add custom driver feature for package gdb 2020-03-08 11:03:18 +08:00
0e52d467d3 improving package gdb 2020-03-08 00:17:42 +08:00
6665d62e7e improve package gfile 2020-03-07 20:28:00 +08:00
5bdf1a71b8 improve uploading file feature for ghttp.Server 2020-03-07 20:20:52 +08:00
a34ca0ff4b improve uploading file feature for ghttp.Server; improve package gfile/gstr/gdebug 2020-03-07 19:31:33 +08:00
7f0163d958 improve gconv.Struct* functions for custom types conversion 2020-03-06 23:22:08 +08:00
31f19b0eee improve package gcompress 2020-03-06 15:38:32 +08:00
93d0760898 add GetPage function for ghttp.Request 2020-03-06 11:01:03 +08:00
4863e7a6ae Merge pull request #529 from wenzi1/master 2020-03-05 22:02:16 +08:00
a161b44cc7 improve package gpage 2020-03-05 18:07:07 +08:00
7072244420 improve comment for ghttp.Server 2020-03-05 16:08:55 +08:00
f68b66e606 update comment for ghttp.Server 2020-03-04 23:32:27 +08:00
4e7c6c1fb4 improve CORS feature for ghttp.Server 2020-03-04 22:52:56 +08:00
d8a7e36478 improve router feature for ghttp.Server 2020-03-04 17:29:23 +08:00
8971ad8445 Add tables method of MSSQL, Oracle and PgSQL 2020-03-02 23:41:33 +08:00
270af8accb Merge pull request #1 from gogf/master
update
2020-02-29 22:46:00 +08:00
b0ef63fc9d improve bindArgsToQuery for surpport for pgsql/mssql/oracle for package gdb 2020-02-29 19:55:53 +08:00
420 changed files with 21079 additions and 15639 deletions

View File

@ -9,7 +9,7 @@ import (
func main() {
// 创建一个对象池过期时间为1000毫秒
p := gpool.New(1000, nil)
p := gpool.New(1000*time.Millisecond, nil)
// 从池中取一个对象返回nil及错误信息
fmt.Println(p.Get())

View File

@ -11,7 +11,7 @@ import (
func main() {
// 创建对象复用池对象过期时间为3000毫秒并给定创建及销毁方法
p := gpool.New(3000, func() (interface{}, error) {
p := gpool.New(3000*time.Millisecond, func() (interface{}, error) {
return gtcp.NewConn("www.baidu.com:80")
}, func(i interface{}) {
glog.Println("expired")

View File

@ -0,0 +1,79 @@
// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package driver
import (
"database/sql"
"github.com/gogf/gf/database/gdb"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/os/gtime"
)
// MyDriver is a custom database driver, which is used for testing only.
// For simplifying the unit testing case purpose, MyDriver struct inherits the mysql driver
// gdb.DriverMysql and overwrites its functions DoQuery and DoExec.
// So if there's any sql execution, it goes through MyDriver.DoQuery/MyDriver.DoExec firstly
// and then gdb.DriverMysql.DoQuery/gdb.DriverMysql.DoExec.
// You can call it sql "HOOK" or "HiJack" as your will.
type MyDriver struct {
*gdb.DriverMysql
}
var (
// customDriverName is my driver name, which is used for registering.
customDriverName = "MyDriver"
)
func init() {
// It here registers my custom driver in package initialization function "init".
// You can later use this type in the database configuration.
if err := gdb.Register(customDriverName, &MyDriver{}); err != nil {
panic(err)
}
}
// New creates and returns a database object for mysql.
// It implements the interface of gdb.Driver for extra database driver installation.
func (d *MyDriver) New(core *gdb.Core, node *gdb.ConfigNode) (gdb.DB, error) {
return &MyDriver{
&gdb.DriverMysql{
Core: core,
},
}, nil
}
// DoQuery commits the sql string and its arguments to underlying driver
// through given link object and returns the execution result.
func (d *MyDriver) DoQuery(link gdb.Link, sql string, args ...interface{}) (rows *sql.Rows, err error) {
tsMilli := gtime.TimestampMilli()
rows, err = d.DriverMysql.DoQuery(link, sql, args...)
if _, err := d.DriverMysql.InsertIgnore("monitor", g.Map{
"sql": gdb.FormatSqlWithArgs(sql, args),
"cost": gtime.TimestampMilli() - tsMilli,
"time": gtime.Now(),
"error": err.Error(),
}); err != nil {
panic(err)
}
return
}
// DoExec commits the query string and its arguments to underlying driver
// through given link object and returns the execution result.
func (d *MyDriver) DoExec(link gdb.Link, sql string, args ...interface{}) (result sql.Result, err error) {
tsMilli := gtime.TimestampMilli()
result, err = d.DriverMysql.DoExec(link, sql, args...)
if _, err := d.DriverMysql.InsertIgnore("monitor", g.Map{
"sql": gdb.FormatSqlWithArgs(sql, args),
"cost": gtime.TimestampMilli() - tsMilli,
"time": gtime.Now(),
"error": err.Error(),
}); err != nil {
panic(err)
}
return
}

View File

@ -0,0 +1 @@
package main

View File

@ -11,11 +11,11 @@ func main() {
// 开启调试模式以便于记录所有执行的SQL
db.SetDebug(true)
r, e := db.Table("test").OrderBy("id asc").All()
r, e := db.Table("test").Order("id asc").All()
if e != nil {
panic(e)
fmt.Println(e)
}
if r != nil {
fmt.Println(r.ToList())
fmt.Println(r.List())
}
}

View File

@ -9,5 +9,4 @@ func main() {
db.SetDebug(true)
db.Table("user").Fields("DISTINCT id,nickname").Filter().All()
}

View File

@ -0,0 +1,17 @@
package main
import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
)
func main() {
s := g.Server()
s.BindHandler("/", func(r *ghttp.Request) {
r.Response.WriteTplContent(`${.name}`, g.Map{
"name": "john",
})
})
s.SetPort(8199)
s.Run()
}

View File

@ -0,0 +1,2 @@
[viewer]
delimiters = ["${", "}"]

View File

@ -8,7 +8,6 @@ import (
func main() {
s := ghttp.GetServer()
s.BindHandler("/", func(r *ghttp.Request) {
r.Response.Write("Hello World")
r.Response.WriteTpl("index.tpl", g.Map{
"title": "Test",
"name": "John",

View File

@ -11,7 +11,7 @@ import (
func main() {
for {
time.Sleep(time.Second)
if f, err := gfpool.Open("/home/john/temp/log.log", os.O_RDONLY, 0666, 60000000*1000); err == nil {
if f, err := gfpool.Open("/home/john/temp/log.log", os.O_RDONLY, 0666, time.Hour); err == nil {
fmt.Println(f.Name())
f.Close()
} else {

View File

@ -0,0 +1,11 @@
package main
import (
"github.com/gogf/gf/os/glog"
)
func main() {
l := glog.New()
l.SetLevelPrefix(glog.LEVEL_DEBU, "debug")
l.Debug("test")
}

View File

@ -1,16 +0,0 @@
package main
import (
"github.com/gogf/gf/os/gres"
_ "github.com/gogf/gf/os/gres/testdata"
)
func main() {
gres.Dump()
//file := gres.Get("www")
//fmt.Println(file.Open())
//g.Dump(gres.ScanDir("/root/image", "*"))
//g.Dump(gres.Scan("/root/image/", "*", true))
//g.Dump(gres.Scan("/template", "*"))
//g.Dump(gres.Scan("/template/layout2", "*.html", true))
}

View File

@ -0,0 +1,20 @@
package main
import (
_ "github.com/gogf/gf/os/gres/testdata/example/boot"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
)
func main() {
s := g.Server()
s.Group("/", func(group *ghttp.RouterGroup) {
group.GET("/template", func(r *ghttp.Request) {
r.Response.WriteTplDefault(g.Map{
"name": "GoFrame",
})
})
})
s.Run()
}

View File

@ -7,6 +7,12 @@
default = "127.0.0.1:6379,0"
cache = "127.0.0.1:6379,1"
# Logger.
[logger]
Path = "/tmp/log/gf-app"
Level = "all"
Stdout = true
[viewer]
delimiters = ["${", "}"]
autoencode = true

View File

@ -1,37 +1,25 @@
package main
import (
"net/http"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
"github.com/gogf/gf/crypto/gaes"
"github.com/gogf/gf/os/gfile"
"github.com/gogf/gf/os/gres"
)
func MiddlewareAuth(r *ghttp.Request) {
token := r.Get("token")
if token == "123456" {
r.Response.Writeln("auth")
r.Middleware.Next()
} else {
r.Response.WriteStatus(http.StatusForbidden)
}
}
func MiddlewareCORS(r *ghttp.Request) {
r.Response.Writeln("cors")
r.Response.CORSDefault()
r.Middleware.Next()
}
var (
CryptoKey = []byte("x76cgqt36i9c863bzmotuf8626dxiwu0")
)
func main() {
s := g.Server()
s.Use(MiddlewareCORS)
s.Group("/api.v2", func(group *ghttp.RouterGroup) {
group.Middleware(MiddlewareAuth)
group.ALL("/user/list", func(r *ghttp.Request) {
r.Response.Writeln("list")
})
})
s.SetPort(8199)
s.Run()
binContent, err := gres.Pack("public,config")
if err != nil {
panic(err)
}
binContent, err = gaes.Encrypt(binContent, CryptoKey)
if err != nil {
panic(err)
}
if err := gfile.PutBytes("data.bin", binContent); err != nil {
panic(err)
}
}

View File

@ -4,13 +4,12 @@ import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
"github.com/gogf/gf/os/gview"
"github.com/gogf/gf/util/gpage"
)
func main() {
s := ghttp.GetServer()
s := g.Server()
s.BindHandler("/page/demo", func(r *ghttp.Request) {
page := gpage.New(100, 10, r.Get("page"), r.URL.String())
page := r.GetPage(100, 10)
buffer, _ := gview.ParseContent(`
<html>
<head>

View File

@ -4,14 +4,13 @@ import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
"github.com/gogf/gf/os/gview"
"github.com/gogf/gf/util/gpage"
)
func main() {
s := ghttp.GetServer()
s := g.Server()
s.BindHandler("/page/ajax", func(r *ghttp.Request) {
page := gpage.New(100, 10, r.Get("page"), r.URL.String(), r.Router)
page.EnableAjax("DoAjax")
page := r.GetPage(100, 10)
page.AjaxActionName = "DoAjax"
buffer, _ := gview.ParseContent(`
<html>
<head>
@ -29,11 +28,17 @@ func main() {
</script>
</head>
<body>
<div>{{.page}}</div>
<div>{{.page1}}</div>
<div>{{.page2}}</div>
<div>{{.page3}}</div>
<div>{{.page4}}</div>
</body>
</html>
`, g.Map{
"page": page.GetContent(1),
"page1": page.GetContent(1),
"page2": page.GetContent(2),
"page3": page.GetContent(3),
"page4": page.GetContent(4),
})
r.Response.Write(buffer)
})

View File

@ -8,7 +8,7 @@ import (
"github.com/gogf/gf/util/gpage"
)
// 分页标签使用li标签包裹
// wrapContent wraps each of the page tag with html li and ul.
func wrapContent(page *gpage.Page) string {
content := page.GetContent(4)
content = gstr.ReplaceByMap(content, map[string]string{
@ -21,9 +21,9 @@ func wrapContent(page *gpage.Page) string {
}
func main() {
s := ghttp.GetServer()
s := g.Server()
s.BindHandler("/page/custom1/*page", func(r *ghttp.Request) {
page := gpage.New(100, 10, r.Get("page"), r.URL.String(), r.Router)
page := r.GetPage(100, 10)
content := wrapContent(page)
buffer, _ := gview.ParseContent(`
<html>

View File

@ -7,7 +7,7 @@ import (
"github.com/gogf/gf/util/gpage"
)
// 自定义分页名称
// pageContent customizes the page tag name.
func pageContent(page *gpage.Page) string {
page.NextPageTag = "NextPage"
page.PrevPageTag = "PrevPage"
@ -15,16 +15,16 @@ func pageContent(page *gpage.Page) string {
page.LastPageTag = "LastPage"
pageStr := page.FirstPage()
pageStr += page.PrevPage()
pageStr += page.PageBar("current-page")
pageStr += page.PageBar()
pageStr += page.NextPage()
pageStr += page.LastPage()
return pageStr
}
func main() {
s := ghttp.GetServer()
s := g.Server()
s.BindHandler("/page/custom2/*page", func(r *ghttp.Request) {
page := gpage.New(100, 10, r.Get("page"), r.URL.String(), r.Router)
page := r.GetPage(100, 10)
buffer, _ := gview.ParseContent(`
<html>
<head>

View File

@ -4,13 +4,12 @@ import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
"github.com/gogf/gf/os/gview"
"github.com/gogf/gf/util/gpage"
)
func main() {
s := g.Server()
s.BindHandler("/page/static/*page", func(r *ghttp.Request) {
page := gpage.New(100, 10, r.Get("page"), r.URL.String(), r.Router)
page := r.GetPage(100, 10)
buffer, _ := gview.ParseContent(`
<html>
<head>

View File

@ -4,13 +4,12 @@ import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
"github.com/gogf/gf/os/gview"
"github.com/gogf/gf/util/gpage"
)
func main() {
s := g.Server()
s.BindHandler("/:obj/*action/{page}.html", func(r *ghttp.Request) {
page := gpage.New(100, 10, r.Get("page"), r.URL.String(), r.Router)
page := r.GetPage(100, 10)
buffer, _ := gview.ParseContent(`
<html>
<head>

View File

@ -4,14 +4,13 @@ import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
"github.com/gogf/gf/os/gview"
"github.com/gogf/gf/util/gpage"
)
func main() {
s := g.Server()
s.BindHandler("/page/template/{page}.html", func(r *ghttp.Request) {
page := gpage.New(100, 10, r.Get("page"), r.URL.String())
page.SetUrlTemplate("/order/list/{.page}.html")
page := r.GetPage(100, 10)
page.UrlTemplate = "/order/list/{.page}.html"
buffer, _ := gview.ParseContent(`
<html>
<head>

View File

@ -1,8 +1,6 @@
language: go
go:
- "1.11.x"
- "1.12.x"
- "1.13.x"
- "1.14.x"

View File

@ -15,7 +15,7 @@ We currently accept donation by Alipay/WechatPay, please note your github/gitee
|[zhuhuan12](https://gitee.com/zhuhuan12)|gitee|¥50.00 |
|[zfan_codes](https://gitee.com/zfan_codes)|gitee|¥10.00 |
|[arden](https://github.com/arden)|alipay|¥10.00 |
|[macnie](https://www.macnie.com)|wechat|¥100.00 |
|[macnie](https://www.macnie.com)|wechat|¥110.00 |
|lah|wechat|¥100.00 |
|x*z|wechat|¥20.00 |
|潘兄|wechat|¥100.00 |
@ -40,7 +40,7 @@ We currently accept donation by Alipay/WechatPay, please note your github/gitee
|R*s|wechat|¥18.88| 谢谢GF辛苦了
|粟*e|wechat|¥50.00|
|[李超](https://github.com/effortlee)|wechat|¥124.00|
|张炳贤|wechat+qq|¥600.00|
|soidea666|wechat+qq|¥800.00|
|[王哈哈](https://gitee.com/develop1024)|wechat|¥6.66| 希望gf越来越好
|夕景|alipay+qq|¥9.96+3.57|
|struggler|alipay|¥18.80|
@ -51,6 +51,24 @@ We currently accept donation by Alipay/WechatPay, please note your github/gitee
|[Zeroing-ZY](https://gitee.com/yunjieg)|gitee|¥20.00| 感谢您的开源项目!
|[katydid酱](https://gitee.com/katydid2005)|gitee|¥50.00| 感谢您的开源项目!框架给予了很大的帮助!谢谢大佬!
|[李海峰](https://gitee.com/dlhf)|gitee|¥10.00| 希望GF越来越好框架很牛逼
|陆昱天|alipay|¥100.00|
|[Dockercore](https://github.com/dockercore)|wechat|¥200.00| 非常喜欢!简洁好用!文档超级全!
|🚶|wechat|¥6.88| 喝杯冰阔落
|a*l|wechat|¥10.00| gf
|[wxkj](https://gitee.com/wxkj)|wechat|¥10.00|
|*包|wechat|¥9.99|
|重庆宝尔威科技|wechat|¥6.66|
|琦玉-QPT|wechat|¥6.66|
|sailsea|wechat|¥11.00|
|[seny0929](https://gitee.com/seny0929)|wechat|¥99.90|
|*华|wechat|¥6.66| 感谢郭强的热心
|[Playhi](https://github.com/Playhi)|alipay|¥10.00|
|北京京纬互动科技|alipay|¥200.00|
|米司特包|wechat|¥99.99|
|金毛|alipay|¥100.00|
|1*1x|wechat|¥100.00|
|[ywanbing](https://github.com/ywanbing)|wechat|¥66.66|
|[侯哥](http://www.macnie.com)|wechat|¥10.00|
<img src="https://goframe.org/images/donate.png"/>

View File

@ -28,7 +28,7 @@ require github.com/gogf/gf latest
# Limitation
```
golang version >= 1.10
golang version >= 1.13
```
# Documentation

View File

@ -8,11 +8,12 @@
[English](README.MD) | 简体中文
`GF(Go Frame)`是一款模块化、高性能、生产级的Go基础开发框架。实现了比较完善的基础设施建设,包括常用的核心开发组件,
如:缓存、日志、文件、时间、队列、数组、集合、字符串、定时器、命令行、文件锁、内存锁、对象池、连接池、资源管理、数据校验、数据编码、文件监控、
定时任务、数据库ORM、TCP/UDP组件、进程管理/通信、并发安全容器等等。
并提供了Web服务开发的系列核心组件Router、Cookie、Session、Middleware、服务注册、配置管理、模板引擎等等
支持热重启、热更新、多域名、多端口、多服务、HTTPS、Rewrite等特性。
`GF(Go Frame)`是一款模块化、高性能、生产级的Go基础开发框架。
实现了比较完善的基础设施建设以及开发工具链,提供了常用的基础开发模块,
如:缓存、日志、队列、数组、集合、容器、定时器、命令行、内存锁、对象池、
配置管理、资源管理、数据校验、数据编码、定时任务、数据库ORM、TCP/UDP组件、进程管理/通信等等
并提供了Web服务开发的系列核心组件Router、Cookie、Session、Middleware、服务注册、模板引擎等等
支持热重启、热更新、域名绑定、TLS/HTTPS、Rewrite等特性。
# 特点
@ -40,7 +41,7 @@ require github.com/gogf/gf latest
# 限制
```shell
golang版本 >= 1.11
golang版本 >= 1.13
```
# 架构

View File

@ -10,7 +10,6 @@
1. gjson对大json数据的解析效率问题
1. ghttp增加route name特性并同时支持backend和template(提供内置函数)引用可以通过RedirectRoute方法给定route name和路由参数跳转到指定的路由地址上
1. gvalid校验支持当第一个规则失败后便不再校验后续的规则最好做成链式操作
1. gvalid增加支持对[]rune的长度校验(一个中文占3个字节)
1. ghttp.Request增加对输入参数的自动HtmlEncode机制
1. 常量命名风格根据golint进行修改
1. 开放rwmutex包并将gjson的互斥锁使用自定义的mutex替换
@ -21,8 +20,6 @@
- ghttp Server&Client basic auth、
- glog分类&日志等级&链式操作、gdb debug自动输出调试信息、gmlock内存锁、
1. 服务注册域名增加对泛域名的支持;
1. Cookie设置中文失效问题
1. 使用gconv将slice映射到struct属性上例如redis hscan的结果集
1. 项目参考:
- https://github.com/namreg/godown
- https://github.com/Masterminds/sprig
@ -31,32 +28,36 @@
1. 路由增加不区分大小写得匹配方式;
1. 改进WebServer获取POST参数处理逻辑当提交非form数据时例如json数据针对某些方法可以直接解析
1. WebServer增加可选择的路由覆盖配置默认情况下不覆盖
1. grpool性能压测结果变慢的问题
1. 增加jumplist的数据结构容器
1. DelayQueue/PriorityQueue
1. 权限管理模块;
1. 从ghttp中剥离SESSION功能构成单独的模块gsession
1. 改进gproc进程间通信处理逻辑提高稳定性以应对进程间大批量的数据发送/接收;
1. ghttp的热重启的本地进程端口监听在不使用该特性时默认关闭掉
1. gtcp增加对TLS加密通信的支持
1. 添加Save/Replace/BatchSave/BatchReplace方法对sqlite数据库的支持
1. 添加sqlite数据库的单元测试用例
1. gredis增加cluster支持
1. gset.Add/Remove/Contains方法增加批量操作支持
1. gmlock增加手动清理机制当内存锁不再使用时由调用端决定是否清理内存锁
1. gtimer增加DelayAdd*方法返回Entry对象以便DelayAdd*的定时任务也能进行状态控制gcron同理需要改进
1. 改进gdb对pgsql/mssql/oracle的支持使用方法覆盖的方式改进操作而不是完全依靠正则替换的方式
1. gdb的Cache缓存功能增加可自定义缓存接口以便支持外部缓存功能缓存接口可以通过io.ReadWriter接口实现
1. grpool增加支持阻塞添加任务接口
1. gdb.Model在链式安全的对象创建中增加sync.Pool的使用
1. 增加g.Table快捷方法以方便操作数据表但是得考虑后续模型操作设计特别是脚手架的模型管理
1. 改进ghttp分组路由中对hook的支持方式以便格式与BindHookHandler统一
# DONE
1. Cookie设置中文失效问题
1. gvalid增加支持对[]rune的长度校验(一个中文占3个字节)
1. grpool性能压测结果变慢的问题
1. ghttp的热重启的本地进程端口监听在不使用该特性时默认关闭掉
1. gtcp增加对TLS加密通信的支持
1. 改进gdb对pgsql/mssql/oracle的支持使用方法覆盖的方式改进操作而不是完全依靠正则替换的方式
1. gdb的Cache缓存功能增加可自定义缓存接口以便支持外部缓存功能缓存接口可以通过io.ReadWriter接口实现
1. 改进ghttp分组路由中对hook的支持方式以便格式与BindHookHandler统一
1. 使用gconv将slice映射到struct属性上例如redis hscan的结果集
1. gconv完善针对不同类型的判断例如尽量减少sprintf("%v", xxx)来执行string类型的转换
2. ghttp.Server请求执行中增加服务退出的方法不再执行后续操作
3. ghttp.Response对象完善并改进数据返回方法(Write/WriteString)

View File

@ -237,6 +237,9 @@ func (a *Array) PopRands(size int) []interface{} {
if size > len(a.array) {
size = len(a.array)
}
if size == 0 {
return nil
}
array := make([]interface{}, size)
for i := 0; i < size; i++ {
index := grand.Intn(len(a.array))
@ -250,6 +253,9 @@ func (a *Array) PopRands(size int) []interface{} {
func (a *Array) PopLeft() interface{} {
a.mu.Lock()
defer a.mu.Unlock()
if len(a.array) == 0 {
return nil
}
value := a.array[0]
a.array = a.array[1:]
return value
@ -260,6 +266,9 @@ func (a *Array) PopRight() interface{} {
a.mu.Lock()
defer a.mu.Unlock()
index := len(a.array) - 1
if index <= 0 {
return nil
}
value := a.array[index]
a.array = a.array[:index]
return value
@ -270,6 +279,9 @@ func (a *Array) PopLefts(size int) []interface{} {
a.mu.Lock()
defer a.mu.Unlock()
length := len(a.array)
if length == 0 {
return nil
}
if size > length {
size = length
}
@ -282,6 +294,9 @@ func (a *Array) PopLefts(size int) []interface{} {
func (a *Array) PopRights(size int) []interface{} {
a.mu.Lock()
defer a.mu.Unlock()
if len(a.array) == 0 {
return nil
}
index := len(a.array) - size
if index < 0 {
index = 0
@ -765,3 +780,8 @@ func (a *Array) FilterEmpty() *Array {
}
return a
}
// IsEmpty checks whether the array is empty.
func (a *Array) IsEmpty() bool {
return a.Len() == 0
}

View File

@ -176,6 +176,7 @@ func (a *IntArray) InsertAfter(index int, value int) *IntArray {
}
// Remove removes an item by index.
// Note that if the index is out of range of array, it returns 0.
func (a *IntArray) Remove(index int) int {
a.mu.Lock()
defer a.mu.Unlock()
@ -228,25 +229,39 @@ func (a *IntArray) PushRight(value ...int) *IntArray {
}
// PopLeft pops and returns an item from the beginning of array.
// Note that if the array is empty, it returns 0.
// Be very careful when use this function in loop statement.
// You can use IsEmpty() of Len() == 0 checks if this array empty.
func (a *IntArray) PopLeft() int {
a.mu.Lock()
defer a.mu.Unlock()
if len(a.array) == 0 {
return 0
}
value := a.array[0]
a.array = a.array[1:]
return value
}
// PopRight pops and returns an item from the end of array.
// Note that if the array is empty, it returns 0.
// Be very careful when use this function in loop statement.
// You can use IsEmpty() of Len() == 0 checks if this array empty.
func (a *IntArray) PopRight() int {
a.mu.Lock()
defer a.mu.Unlock()
index := len(a.array) - 1
if index <= 0 {
return 0
}
value := a.array[index]
a.array = a.array[:index]
return value
}
// PopRand randomly pops and return an item out of array.
// Be very careful when use this function in loop statement.
// You can use IsEmpty() of Len() == 0 checks if this array empty.
func (a *IntArray) PopRand() int {
return a.Remove(grand.Intn(len(a.array)))
}
@ -258,6 +273,9 @@ func (a *IntArray) PopRands(size int) []int {
if size > len(a.array) {
size = len(a.array)
}
if size == 0 {
return nil
}
array := make([]int, size)
for i := 0; i < size; i++ {
index := grand.Intn(len(a.array))
@ -272,6 +290,9 @@ func (a *IntArray) PopLefts(size int) []int {
a.mu.Lock()
defer a.mu.Unlock()
length := len(a.array)
if length == 0 {
return nil
}
if size > length {
size = length
}
@ -284,6 +305,9 @@ func (a *IntArray) PopLefts(size int) []int {
func (a *IntArray) PopRights(size int) []int {
a.mu.Lock()
defer a.mu.Unlock()
if len(a.array) == 0 {
return nil
}
index := len(a.array) - size
if index < 0 {
index = 0
@ -730,3 +754,8 @@ func (a *IntArray) FilterEmpty() *IntArray {
}
return a
}
// IsEmpty checks whether the array is empty.
func (a *IntArray) IsEmpty() bool {
return a.Len() == 0
}

View File

@ -162,6 +162,7 @@ func (a *StrArray) InsertAfter(index int, value string) *StrArray {
}
// Remove removes an item by index.
// Note that if the index is out of range of array, it returns an empty string.
func (a *StrArray) Remove(index int) string {
a.mu.Lock()
defer a.mu.Unlock()
@ -214,25 +215,40 @@ func (a *StrArray) PushRight(value ...string) *StrArray {
}
// PopLeft pops and returns an item from the beginning of array.
// Note that if the array is empty, it returns an empty string.
// Be very careful when use this function in loop statement.
// You can use IsEmpty() of Len() == 0 checks if this array empty.
func (a *StrArray) PopLeft() string {
a.mu.Lock()
defer a.mu.Unlock()
if len(a.array) == 0 {
return ""
}
value := a.array[0]
a.array = a.array[1:]
return value
}
// PopRight pops and returns an item from the end of array.
// Note that if the array is empty, it returns an empty string.
// Be very careful when use this function in loop statement.
// You can use IsEmpty() of Len() == 0 checks if this array empty.
func (a *StrArray) PopRight() string {
a.mu.Lock()
defer a.mu.Unlock()
index := len(a.array) - 1
if index <= 0 {
return ""
}
value := a.array[index]
a.array = a.array[:index]
return value
}
// PopRand randomly pops and return an item out of array.
// Note that if the array is empty, it returns an empty string.
// Be very careful when use this function in loop statement.
// You can use IsEmpty() of Len() == 0 checks if this array empty.
func (a *StrArray) PopRand() string {
return a.Remove(grand.Intn(len(a.array)))
}
@ -244,6 +260,9 @@ func (a *StrArray) PopRands(size int) []string {
if size > len(a.array) {
size = len(a.array)
}
if size == 0 {
return nil
}
array := make([]string, size)
for i := 0; i < size; i++ {
index := grand.Intn(len(a.array))
@ -261,6 +280,9 @@ func (a *StrArray) PopLefts(size int) []string {
if size > length {
size = length
}
if size == 0 {
return nil
}
value := a.array[0:size]
a.array = a.array[size:]
return value
@ -270,6 +292,9 @@ func (a *StrArray) PopLefts(size int) []string {
func (a *StrArray) PopRights(size int) []string {
a.mu.Lock()
defer a.mu.Unlock()
if len(a.array) == 0 {
return nil
}
index := len(a.array) - size
if index < 0 {
index = 0
@ -730,3 +755,8 @@ func (a *StrArray) FilterEmpty() *StrArray {
}
return a
}
// IsEmpty checks whether the array is empty.
func (a *StrArray) IsEmpty() bool {
return a.Len() == 0
}

View File

@ -33,9 +33,9 @@ type SortedArray struct {
// NewSortedArray creates and returns an empty sorted array.
// The parameter <safe> is used to specify whether using array in concurrent-safety, which is false in default.
// The parameter <comparator> used to compare values to sort in array,
// if it returns value < 0, means v1 < v2;
// if it returns value = 0, means v1 = v2;
// if it returns value > 0, means v1 > v2;
// if it returns value < 0, means v1 < v2; the v1 will be inserted before v2;
// if it returns value = 0, means v1 = v2; the v1 will be replaced by v2;
// if it returns value > 0, means v1 > v2; the v1 will be inserted after v2;
func NewSortedArray(comparator func(a, b interface{}) int, safe ...bool) *SortedArray {
return NewSortedArraySize(0, comparator, safe...)
}
@ -196,6 +196,9 @@ func (a *SortedArray) RemoveValue(value interface{}) bool {
func (a *SortedArray) PopLeft() interface{} {
a.mu.Lock()
defer a.mu.Unlock()
if len(a.array) == 0 {
return nil
}
value := a.array[0]
a.array = a.array[1:]
return value
@ -206,6 +209,9 @@ func (a *SortedArray) PopRight() interface{} {
a.mu.Lock()
defer a.mu.Unlock()
index := len(a.array) - 1
if index <= 0 {
return nil
}
value := a.array[index]
a.array = a.array[:index]
return value
@ -223,6 +229,9 @@ func (a *SortedArray) PopRands(size int) []interface{} {
if size > len(a.array) {
size = len(a.array)
}
if size == 0 {
return nil
}
array := make([]interface{}, size)
for i := 0; i < size; i++ {
index := grand.Intn(len(a.array))
@ -240,6 +249,9 @@ func (a *SortedArray) PopLefts(size int) []interface{} {
if size > length {
size = length
}
if size == 0 {
return nil
}
value := a.array[0:size]
a.array = a.array[size:]
return value
@ -249,6 +261,9 @@ func (a *SortedArray) PopLefts(size int) []interface{} {
func (a *SortedArray) PopRights(size int) []interface{} {
a.mu.Lock()
defer a.mu.Unlock()
if len(a.array) == 0 {
return nil
}
index := len(a.array) - size
if index < 0 {
index = 0
@ -439,6 +454,9 @@ func (a *SortedArray) SetUnique(unique bool) *SortedArray {
func (a *SortedArray) Unique() *SortedArray {
a.mu.Lock()
defer a.mu.Unlock()
if len(a.array) == 0 {
return a
}
i := 0
for {
if i == len(a.array)-1 {
@ -730,3 +748,8 @@ func (a *SortedArray) FilterEmpty() *SortedArray {
}
return a
}
// IsEmpty checks whether the array is empty.
func (a *SortedArray) IsEmpty() bool {
return a.Len() == 0
}

View File

@ -143,6 +143,7 @@ func (a *SortedIntArray) Get(index int) int {
}
// Remove removes an item by index.
// Note that if the index is out of range of array, it returns 0.
func (a *SortedIntArray) Remove(index int) int {
a.mu.Lock()
defer a.mu.Unlock()
@ -178,25 +179,40 @@ func (a *SortedIntArray) RemoveValue(value int) bool {
}
// PopLeft pops and returns an item from the beginning of array.
// Note that if the array is empty, it returns 0.
// Be very careful when use this function in loop statement.
// You can use IsEmpty() of Len() == 0 checks if this array empty.
func (a *SortedIntArray) PopLeft() int {
a.mu.Lock()
defer a.mu.Unlock()
if len(a.array) == 0 {
return 0
}
value := a.array[0]
a.array = a.array[1:]
return value
}
// PopRight pops and returns an item from the end of array.
// Note that if the array is empty, it returns 0.
// Be very careful when use this function in loop statement.
// You can use IsEmpty() of Len() == 0 checks if this array empty.
func (a *SortedIntArray) PopRight() int {
a.mu.Lock()
defer a.mu.Unlock()
index := len(a.array) - 1
if index <= 0 {
return 0
}
value := a.array[index]
a.array = a.array[:index]
return value
}
// PopRand randomly pops and return an item out of array.
// Note that if the array is empty, it returns 0.
// Be very careful when use this function in loop statement.
// You can use IsEmpty() of Len() == 0 checks if this array empty.
func (a *SortedIntArray) PopRand() int {
return a.Remove(grand.Intn(len(a.array)))
}
@ -208,6 +224,9 @@ func (a *SortedIntArray) PopRands(size int) []int {
if size > len(a.array) {
size = len(a.array)
}
if size == 0 {
return nil
}
array := make([]int, size)
for i := 0; i < size; i++ {
index := grand.Intn(len(a.array))
@ -225,6 +244,9 @@ func (a *SortedIntArray) PopLefts(size int) []int {
if size > length {
size = length
}
if size == 0 {
return nil
}
value := a.array[0:size]
a.array = a.array[size:]
return value
@ -234,6 +256,9 @@ func (a *SortedIntArray) PopLefts(size int) []int {
func (a *SortedIntArray) PopRights(size int) []int {
a.mu.Lock()
defer a.mu.Unlock()
if len(a.array) == 0 {
return nil
}
index := len(a.array) - size
if index < 0 {
index = 0
@ -429,6 +454,10 @@ func (a *SortedIntArray) SetUnique(unique bool) *SortedIntArray {
// Unique uniques the array, clear repeated items.
func (a *SortedIntArray) Unique() *SortedIntArray {
a.mu.Lock()
defer a.mu.Unlock()
if len(a.array) == 0 {
return a
}
i := 0
for {
if i == len(a.array)-1 {
@ -440,7 +469,6 @@ func (a *SortedIntArray) Unique() *SortedIntArray {
i++
}
}
a.mu.Unlock()
return a
}
@ -677,3 +705,8 @@ func (a *SortedIntArray) FilterEmpty() *SortedIntArray {
}
return a
}
// IsEmpty checks whether the array is empty.
func (a *SortedIntArray) IsEmpty() bool {
return a.Len() == 0
}

View File

@ -128,6 +128,7 @@ func (a *SortedStrArray) Get(index int) string {
}
// Remove removes an item by index.
// Note that if the index is out of range of array, it returns an empty string.
func (a *SortedStrArray) Remove(index int) string {
a.mu.Lock()
defer a.mu.Unlock()
@ -163,25 +164,40 @@ func (a *SortedStrArray) RemoveValue(value string) bool {
}
// PopLeft pops and returns an item from the beginning of array.
// Note that if the array is empty, it returns an empty string.
// Be very careful when use this function in loop statement.
// You can use IsEmpty() of Len() == 0 checks if this array empty.
func (a *SortedStrArray) PopLeft() string {
a.mu.Lock()
defer a.mu.Unlock()
if len(a.array) == 0 {
return ""
}
value := a.array[0]
a.array = a.array[1:]
return value
}
// PopRight pops and returns an item from the end of array.
// Note that if the array is empty, it returns an empty string.
// Be very careful when use this function in loop statement.
// You can use IsEmpty() of Len() == 0 checks if this array empty.
func (a *SortedStrArray) PopRight() string {
a.mu.Lock()
defer a.mu.Unlock()
index := len(a.array) - 1
if index <= 0 {
return ""
}
value := a.array[index]
a.array = a.array[:index]
return value
}
// PopRand randomly pops and return an item out of array.
// Note that if the array is empty, it returns an empty string.
// Be very careful when use this function in loop statement.
// You can use IsEmpty() of Len() == 0 checks if this array empty.
func (a *SortedStrArray) PopRand() string {
return a.Remove(grand.Intn(len(a.array)))
}
@ -193,6 +209,9 @@ func (a *SortedStrArray) PopRands(size int) []string {
if size > len(a.array) {
size = len(a.array)
}
if size == 0 {
return nil
}
array := make([]string, size)
for i := 0; i < size; i++ {
index := grand.Intn(len(a.array))
@ -210,6 +229,9 @@ func (a *SortedStrArray) PopLefts(size int) []string {
if size > length {
size = length
}
if size == 0 {
return nil
}
value := a.array[0:size]
a.array = a.array[size:]
return value
@ -219,6 +241,9 @@ func (a *SortedStrArray) PopLefts(size int) []string {
func (a *SortedStrArray) PopRights(size int) []string {
a.mu.Lock()
defer a.mu.Unlock()
if len(a.array) == 0 {
return nil
}
index := len(a.array) - size
if index < 0 {
index = 0
@ -414,6 +439,10 @@ func (a *SortedStrArray) SetUnique(unique bool) *SortedStrArray {
// Unique uniques the array, clear repeated items.
func (a *SortedStrArray) Unique() *SortedStrArray {
a.mu.Lock()
defer a.mu.Unlock()
if len(a.array) == 0 {
return a
}
i := 0
for {
if i == len(a.array)-1 {
@ -425,7 +454,6 @@ func (a *SortedStrArray) Unique() *SortedStrArray {
i++
}
}
a.mu.Unlock()
return a
}
@ -673,3 +701,8 @@ func (a *SortedStrArray) FilterEmpty() *SortedStrArray {
}
return a
}
// IsEmpty checks whether the array is empty.
func (a *SortedStrArray) IsEmpty() bool {
return a.Len() == 0
}

View File

@ -8,51 +8,52 @@ package garray_test
import (
"fmt"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/container/garray"
)
func Example_basic() {
// 创建普通的数组,默认并发安全(带锁)
a := garray.New(true)
// A normal array.
a := garray.New()
// 添加数据项
// Adding items.
for i := 0; i < 10; i++ {
a.Append(i)
}
// 获取当前数组长度
// Print the array length.
fmt.Println(a.Len())
// 获取当前数据项列表
// Print the array items.
fmt.Println(a.Slice())
// 获取指定索引项
// Retrieve item by index.
fmt.Println(a.Get(6))
// 查找指定数据项是否存在
// Check item existence.
fmt.Println(a.Contains(6))
fmt.Println(a.Contains(100))
// 在指定索引前插入数据项
// Insert item before specified index.
a.InsertAfter(9, 11)
// 在指定索引后插入数据项
// Insert item after specified index.
a.InsertBefore(10, 10)
fmt.Println(a.Slice())
// 修改指定索引的数据项
// Modify item by index.
a.Set(0, 100)
fmt.Println(a.Slice())
// 搜索数据项,返回搜索到的索引位置
// Search item and return its index.
fmt.Println(a.Search(5))
// 删除指定索引的数据项
// Remove item by index.
a.Remove(0)
fmt.Println(a.Slice())
// 清空数组
// Empty the array, removes all items of it.
fmt.Println(a.Slice())
a.Clear()
fmt.Println(a.Slice())
@ -73,13 +74,21 @@ func Example_basic() {
func Example_rand() {
array := garray.NewFrom([]interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9})
// 随机返回两个数据项(不删除)
// Randomly retrieve and return 2 items from the array.
// It does not delete the items from array.
fmt.Println(array.Rands(2))
// Randomly pick and return one item from the array.
// It deletes the picked up item from array.
fmt.Println(array.PopRand())
}
func Example_pop() {
func Example_popItem() {
array := garray.NewFrom([]interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9})
// Any Pop* functions pick, delete and return the item from array.
fmt.Println(array.PopLeft())
fmt.Println(array.PopLefts(2))
fmt.Println(array.PopRight())
@ -92,7 +101,7 @@ func Example_pop() {
// [7 8]
}
func Example_merge() {
func Example_mergeArray() {
array1 := garray.NewFrom([]interface{}{1, 2})
array2 := garray.NewFrom([]interface{}{3, 4})
slice1 := []interface{}{5, 6}
@ -110,3 +119,14 @@ func Example_merge() {
// [1 2]
// [1 2 1 2 3 4 5 6 7 8 9 0]
}
func Example_filter() {
array1 := garray.NewFrom(g.Slice{0, 1, 2, nil, "", g.Slice{}, "john"})
array2 := garray.NewFrom(g.Slice{0, 1, 2, nil, "", g.Slice{}, "john"})
fmt.Printf("%#v\n", array1.FilterNil().Slice())
fmt.Printf("%#v\n", array2.FilterEmpty().Slice())
// Output:
// []interface {}{0, 1, 2, "", []interface {}{}, "john"}
// []interface {}{1, 2, "john"}
}

View File

@ -18,89 +18,103 @@ import (
)
func Test_IntArray_Unique(t *testing.T) {
expect := []int{1, 2, 3, 4, 5, 6}
array := garray.NewIntArray()
array.Append(1, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6)
array.Unique()
gtest.Assert(array.Slice(), expect)
gtest.C(t, func(t *gtest.T) {
expect := []int{1, 2, 3, 4, 5, 6}
array := garray.NewIntArray()
array.Append(1, 1, 2, 3, 3, 4, 4, 5, 5, 6, 6)
array.Unique()
t.Assert(array.Slice(), expect)
})
}
func Test_SortedIntArray1(t *testing.T) {
expect := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
array := garray.NewSortedIntArray()
for i := 10; i > -1; i-- {
array.Add(i)
}
gtest.Assert(array.Slice(), expect)
gtest.Assert(array.Add().Slice(), expect)
gtest.C(t, func(t *gtest.T) {
expect := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
array := garray.NewSortedIntArray()
for i := 10; i > -1; i-- {
array.Add(i)
}
t.Assert(array.Slice(), expect)
t.Assert(array.Add().Slice(), expect)
})
}
func Test_SortedIntArray2(t *testing.T) {
expect := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
array := garray.NewSortedIntArray()
for i := 0; i <= 10; i++ {
array.Add(i)
}
gtest.Assert(array.Slice(), expect)
gtest.C(t, func(t *gtest.T) {
expect := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
array := garray.NewSortedIntArray()
for i := 0; i <= 10; i++ {
array.Add(i)
}
t.Assert(array.Slice(), expect)
})
}
func Test_SortedStrArray1(t *testing.T) {
expect := []string{"0", "1", "10", "2", "3", "4", "5", "6", "7", "8", "9"}
array1 := garray.NewSortedStrArray()
array2 := garray.NewSortedStrArray(true)
for i := 10; i > -1; i-- {
array1.Add(gconv.String(i))
array2.Add(gconv.String(i))
}
gtest.Assert(array1.Slice(), expect)
gtest.Assert(array2.Slice(), expect)
gtest.C(t, func(t *gtest.T) {
expect := []string{"0", "1", "10", "2", "3", "4", "5", "6", "7", "8", "9"}
array1 := garray.NewSortedStrArray()
array2 := garray.NewSortedStrArray(true)
for i := 10; i > -1; i-- {
array1.Add(gconv.String(i))
array2.Add(gconv.String(i))
}
t.Assert(array1.Slice(), expect)
t.Assert(array2.Slice(), expect)
})
}
func Test_SortedStrArray2(t *testing.T) {
expect := []string{"0", "1", "10", "2", "3", "4", "5", "6", "7", "8", "9"}
array := garray.NewSortedStrArray()
for i := 0; i <= 10; i++ {
array.Add(gconv.String(i))
}
gtest.Assert(array.Slice(), expect)
array.Add()
gtest.Assert(array.Slice(), expect)
gtest.C(t, func(t *gtest.T) {
expect := []string{"0", "1", "10", "2", "3", "4", "5", "6", "7", "8", "9"}
array := garray.NewSortedStrArray()
for i := 0; i <= 10; i++ {
array.Add(gconv.String(i))
}
t.Assert(array.Slice(), expect)
array.Add()
t.Assert(array.Slice(), expect)
})
}
func Test_SortedArray1(t *testing.T) {
expect := []string{"0", "1", "10", "2", "3", "4", "5", "6", "7", "8", "9"}
array := garray.NewSortedArray(func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
gtest.C(t, func(t *gtest.T) {
expect := []string{"0", "1", "10", "2", "3", "4", "5", "6", "7", "8", "9"}
array := garray.NewSortedArray(func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
})
for i := 10; i > -1; i-- {
array.Add(gconv.String(i))
}
t.Assert(array.Slice(), expect)
})
for i := 10; i > -1; i-- {
array.Add(gconv.String(i))
}
gtest.Assert(array.Slice(), expect)
}
func Test_SortedArray2(t *testing.T) {
expect := []string{"0", "1", "10", "2", "3", "4", "5", "6", "7", "8", "9"}
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
}
array := garray.NewSortedArray(func1)
array2 := garray.NewSortedArray(func1, true)
for i := 0; i <= 10; i++ {
array.Add(gconv.String(i))
array2.Add(gconv.String(i))
}
gtest.Assert(array.Slice(), expect)
gtest.Assert(array.Add().Slice(), expect)
gtest.Assert(array2.Slice(), expect)
gtest.C(t, func(t *gtest.T) {
expect := []string{"0", "1", "10", "2", "3", "4", "5", "6", "7", "8", "9"}
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
}
array := garray.NewSortedArray(func1)
array2 := garray.NewSortedArray(func1, true)
for i := 0; i <= 10; i++ {
array.Add(gconv.String(i))
array2.Add(gconv.String(i))
}
t.Assert(array.Slice(), expect)
t.Assert(array.Add().Slice(), expect)
t.Assert(array2.Slice(), expect)
})
}
func TestNewFromCopy(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"100", "200", "300", "400", "500", "600"}
array1 := garray.NewFromCopy(a1)
gtest.AssertIN(array1.PopRands(2), a1)
gtest.Assert(len(array1.PopRands(1)), 1)
gtest.Assert(len(array1.PopRands(9)), 3)
t.AssertIN(array1.PopRands(2), a1)
t.Assert(len(array1.PopRands(1)), 1)
t.Assert(len(array1.PopRands(9)), 3)
})
}

View File

@ -20,41 +20,41 @@ import (
)
func Test_Array_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
expect := []interface{}{0, 1, 2, 3}
array := garray.NewArrayFrom(expect)
array2 := garray.NewArrayFrom(expect)
array3 := garray.NewArrayFrom([]interface{}{})
gtest.Assert(array.Slice(), expect)
gtest.Assert(array.Interfaces(), expect)
t.Assert(array.Slice(), expect)
t.Assert(array.Interfaces(), expect)
array.Set(0, 100)
gtest.Assert(array.Get(0), 100)
gtest.Assert(array.Get(1), 1)
gtest.Assert(array.Search(100), 0)
gtest.Assert(array3.Search(100), -1)
gtest.Assert(array.Contains(100), true)
gtest.Assert(array.Remove(0), 100)
gtest.Assert(array.Remove(-1), nil)
gtest.Assert(array.Remove(100000), nil)
t.Assert(array.Get(0), 100)
t.Assert(array.Get(1), 1)
t.Assert(array.Search(100), 0)
t.Assert(array3.Search(100), -1)
t.Assert(array.Contains(100), true)
t.Assert(array.Remove(0), 100)
t.Assert(array.Remove(-1), nil)
t.Assert(array.Remove(100000), nil)
gtest.Assert(array2.Remove(3), 3)
gtest.Assert(array2.Remove(1), 1)
t.Assert(array2.Remove(3), 3)
t.Assert(array2.Remove(1), 1)
gtest.Assert(array.Contains(100), false)
t.Assert(array.Contains(100), false)
array.Append(4)
gtest.Assert(array.Len(), 4)
t.Assert(array.Len(), 4)
array.InsertBefore(0, 100)
array.InsertAfter(0, 200)
gtest.Assert(array.Slice(), []interface{}{100, 200, 2, 2, 3, 4})
t.Assert(array.Slice(), []interface{}{100, 200, 2, 2, 3, 4})
array.InsertBefore(5, 300)
array.InsertAfter(6, 400)
gtest.Assert(array.Slice(), []interface{}{100, 200, 2, 2, 3, 300, 4, 400})
gtest.Assert(array.Clear().Len(), 0)
t.Assert(array.Slice(), []interface{}{100, 200, 2, 2, 3, 300, 4, 400})
t.Assert(array.Clear().Len(), 0)
})
}
func TestArray_Sort(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
expect1 := []interface{}{0, 1, 2, 3}
expect2 := []interface{}{3, 2, 1, 0}
array := garray.NewArray()
@ -64,78 +64,88 @@ func TestArray_Sort(t *testing.T) {
array.SortFunc(func(v1, v2 interface{}) bool {
return v1.(int) < v2.(int)
})
gtest.Assert(array.Slice(), expect1)
t.Assert(array.Slice(), expect1)
array.SortFunc(func(v1, v2 interface{}) bool {
return v1.(int) > v2.(int)
})
gtest.Assert(array.Slice(), expect2)
t.Assert(array.Slice(), expect2)
})
}
func TestArray_Unique(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
expect := []interface{}{1, 1, 2, 3}
array := garray.NewArrayFrom(expect)
gtest.Assert(array.Unique().Slice(), []interface{}{1, 2, 3})
t.Assert(array.Unique().Slice(), []interface{}{1, 2, 3})
})
}
func TestArray_PushAndPop(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
expect := []interface{}{0, 1, 2, 3}
array := garray.NewArrayFrom(expect)
gtest.Assert(array.Slice(), expect)
gtest.Assert(array.PopLeft(), 0)
gtest.Assert(array.PopRight(), 3)
gtest.AssertIN(array.PopRand(), []interface{}{1, 2})
gtest.AssertIN(array.PopRand(), []interface{}{1, 2})
gtest.Assert(array.Len(), 0)
t.Assert(array.Slice(), expect)
t.Assert(array.PopLeft(), 0)
t.Assert(array.PopRight(), 3)
t.AssertIN(array.PopRand(), []interface{}{1, 2})
t.AssertIN(array.PopRand(), []interface{}{1, 2})
t.Assert(array.Len(), 0)
array.PushLeft(1).PushRight(2)
gtest.Assert(array.Slice(), []interface{}{1, 2})
t.Assert(array.Slice(), []interface{}{1, 2})
})
}
func TestArray_PopRands(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{100, 200, 300, 400, 500, 600}
array := garray.NewFromCopy(a1)
gtest.AssertIN(array.PopRands(2), []interface{}{100, 200, 300, 400, 500, 600})
t.AssertIN(array.PopRands(2), []interface{}{100, 200, 300, 400, 500, 600})
})
}
func TestArray_PopLeftsAndPopRights(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array := garray.New()
t.Assert(array.PopLeft(), nil)
t.Assert(array.PopLefts(10), nil)
t.Assert(array.PopRight(), nil)
t.Assert(array.PopRights(10), nil)
t.Assert(array.PopRand(), nil)
t.Assert(array.PopRands(10), nil)
})
gtest.C(t, func(t *gtest.T) {
value1 := []interface{}{0, 1, 2, 3, 4, 5, 6}
value2 := []interface{}{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewArrayFrom(value1)
array2 := garray.NewArrayFrom(value2)
gtest.Assert(array1.PopLefts(2), []interface{}{0, 1})
gtest.Assert(array1.Slice(), []interface{}{2, 3, 4, 5, 6})
gtest.Assert(array1.PopRights(2), []interface{}{5, 6})
gtest.Assert(array1.Slice(), []interface{}{2, 3, 4})
gtest.Assert(array1.PopRights(20), []interface{}{2, 3, 4})
gtest.Assert(array1.Slice(), []interface{}{})
gtest.Assert(array2.PopLefts(20), []interface{}{0, 1, 2, 3, 4, 5, 6})
gtest.Assert(array2.Slice(), []interface{}{})
t.Assert(array1.PopLefts(2), []interface{}{0, 1})
t.Assert(array1.Slice(), []interface{}{2, 3, 4, 5, 6})
t.Assert(array1.PopRights(2), []interface{}{5, 6})
t.Assert(array1.Slice(), []interface{}{2, 3, 4})
t.Assert(array1.PopRights(20), []interface{}{2, 3, 4})
t.Assert(array1.Slice(), []interface{}{})
t.Assert(array2.PopLefts(20), []interface{}{0, 1, 2, 3, 4, 5, 6})
t.Assert(array2.Slice(), []interface{}{})
})
}
func TestArray_Range(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
value1 := []interface{}{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewArrayFrom(value1)
array2 := garray.NewArrayFrom(value1, true)
gtest.Assert(array1.Range(0, 1), []interface{}{0})
gtest.Assert(array1.Range(1, 2), []interface{}{1})
gtest.Assert(array1.Range(0, 2), []interface{}{0, 1})
gtest.Assert(array1.Range(-1, 10), value1)
gtest.Assert(array1.Range(10, 2), nil)
gtest.Assert(array2.Range(1, 3), []interface{}{1, 2})
t.Assert(array1.Range(0, 1), []interface{}{0})
t.Assert(array1.Range(1, 2), []interface{}{1})
t.Assert(array1.Range(0, 2), []interface{}{0, 1})
t.Assert(array1.Range(-1, 10), value1)
t.Assert(array1.Range(10, 2), nil)
t.Assert(array2.Range(1, 3), []interface{}{1, 2})
})
}
func TestArray_Merge(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
func1 := func(v1, v2 interface{}) int {
if gconv.Int(v1) < gconv.Int(v2) {
return 0
@ -147,7 +157,7 @@ func TestArray_Merge(t *testing.T) {
i2 := []interface{}{4, 5, 6, 7}
array1 := garray.NewArrayFrom(i1)
array2 := garray.NewArrayFrom(i2)
gtest.Assert(array1.Merge(array2).Slice(), []interface{}{0, 1, 2, 3, 4, 5, 6, 7})
t.Assert(array1.Merge(array2).Slice(), []interface{}{0, 1, 2, 3, 4, 5, 6, 7})
//s1 := []string{"a", "b", "c", "d"}
s2 := []string{"e", "f"}
@ -159,185 +169,185 @@ func TestArray_Merge(t *testing.T) {
s6 := garray.NewSortedIntArrayFrom([]int{1, 2, 3})
a1 := garray.NewArrayFrom(i1)
gtest.Assert(a1.Merge(s2).Len(), 6)
gtest.Assert(a1.Merge(i3).Len(), 9)
gtest.Assert(a1.Merge(i4).Len(), 10)
gtest.Assert(a1.Merge(s3).Len(), 12)
gtest.Assert(a1.Merge(s4).Len(), 14)
gtest.Assert(a1.Merge(s5).Len(), 16)
gtest.Assert(a1.Merge(s6).Len(), 19)
t.Assert(a1.Merge(s2).Len(), 6)
t.Assert(a1.Merge(i3).Len(), 9)
t.Assert(a1.Merge(i4).Len(), 10)
t.Assert(a1.Merge(s3).Len(), 12)
t.Assert(a1.Merge(s4).Len(), 14)
t.Assert(a1.Merge(s5).Len(), 16)
t.Assert(a1.Merge(s6).Len(), 19)
})
}
func TestArray_Fill(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{0}
a2 := []interface{}{0}
array1 := garray.NewArrayFrom(a1)
array2 := garray.NewArrayFrom(a2, true)
gtest.Assert(array1.Fill(1, 2, 100).Slice(), []interface{}{0, 100, 100})
gtest.Assert(array2.Fill(0, 2, 100).Slice(), []interface{}{100, 100})
gtest.Assert(array2.Fill(-1, 2, 100).Slice(), []interface{}{100, 100})
t.Assert(array1.Fill(1, 2, 100).Slice(), []interface{}{0, 100, 100})
t.Assert(array2.Fill(0, 2, 100).Slice(), []interface{}{100, 100})
t.Assert(array2.Fill(-1, 2, 100).Slice(), []interface{}{100, 100})
})
}
func TestArray_Chunk(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{1, 2, 3, 4, 5}
array1 := garray.NewArrayFrom(a1)
chunks := array1.Chunk(2)
gtest.Assert(len(chunks), 3)
gtest.Assert(chunks[0], []interface{}{1, 2})
gtest.Assert(chunks[1], []interface{}{3, 4})
gtest.Assert(chunks[2], []interface{}{5})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 3)
t.Assert(chunks[0], []interface{}{1, 2})
t.Assert(chunks[1], []interface{}{3, 4})
t.Assert(chunks[2], []interface{}{5})
t.Assert(array1.Chunk(0), nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{1, 2, 3, 4, 5}
array1 := garray.NewArrayFrom(a1)
chunks := array1.Chunk(3)
gtest.Assert(len(chunks), 2)
gtest.Assert(chunks[0], []interface{}{1, 2, 3})
gtest.Assert(chunks[1], []interface{}{4, 5})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 2)
t.Assert(chunks[0], []interface{}{1, 2, 3})
t.Assert(chunks[1], []interface{}{4, 5})
t.Assert(array1.Chunk(0), nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{1, 2, 3, 4, 5, 6}
array1 := garray.NewArrayFrom(a1)
chunks := array1.Chunk(2)
gtest.Assert(len(chunks), 3)
gtest.Assert(chunks[0], []interface{}{1, 2})
gtest.Assert(chunks[1], []interface{}{3, 4})
gtest.Assert(chunks[2], []interface{}{5, 6})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 3)
t.Assert(chunks[0], []interface{}{1, 2})
t.Assert(chunks[1], []interface{}{3, 4})
t.Assert(chunks[2], []interface{}{5, 6})
t.Assert(array1.Chunk(0), nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{1, 2, 3, 4, 5, 6}
array1 := garray.NewArrayFrom(a1)
chunks := array1.Chunk(3)
gtest.Assert(len(chunks), 2)
gtest.Assert(chunks[0], []interface{}{1, 2, 3})
gtest.Assert(chunks[1], []interface{}{4, 5, 6})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 2)
t.Assert(chunks[0], []interface{}{1, 2, 3})
t.Assert(chunks[1], []interface{}{4, 5, 6})
t.Assert(array1.Chunk(0), nil)
})
}
func TestArray_Pad(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{0}
array1 := garray.NewArrayFrom(a1)
gtest.Assert(array1.Pad(3, 1).Slice(), []interface{}{0, 1, 1})
gtest.Assert(array1.Pad(-4, 1).Slice(), []interface{}{1, 0, 1, 1})
gtest.Assert(array1.Pad(3, 1).Slice(), []interface{}{1, 0, 1, 1})
t.Assert(array1.Pad(3, 1).Slice(), []interface{}{0, 1, 1})
t.Assert(array1.Pad(-4, 1).Slice(), []interface{}{1, 0, 1, 1})
t.Assert(array1.Pad(3, 1).Slice(), []interface{}{1, 0, 1, 1})
})
}
func TestArray_SubSlice(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewArrayFrom(a1)
array2 := garray.NewArrayFrom(a1, true)
gtest.Assert(array1.SubSlice(0, 2), []interface{}{0, 1})
gtest.Assert(array1.SubSlice(2, 2), []interface{}{2, 3})
gtest.Assert(array1.SubSlice(5, 8), []interface{}{5, 6})
gtest.Assert(array1.SubSlice(9, 1), nil)
gtest.Assert(array1.SubSlice(-2, 2), []interface{}{5, 6})
gtest.Assert(array1.SubSlice(-9, 2), nil)
gtest.Assert(array1.SubSlice(1, -2), nil)
gtest.Assert(array2.SubSlice(0, 2), []interface{}{0, 1})
t.Assert(array1.SubSlice(0, 2), []interface{}{0, 1})
t.Assert(array1.SubSlice(2, 2), []interface{}{2, 3})
t.Assert(array1.SubSlice(5, 8), []interface{}{5, 6})
t.Assert(array1.SubSlice(9, 1), nil)
t.Assert(array1.SubSlice(-2, 2), []interface{}{5, 6})
t.Assert(array1.SubSlice(-9, 2), nil)
t.Assert(array1.SubSlice(1, -2), nil)
t.Assert(array2.SubSlice(0, 2), []interface{}{0, 1})
})
}
func TestArray_Rand(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewArrayFrom(a1)
gtest.Assert(len(array1.Rands(2)), 2)
gtest.Assert(len(array1.Rands(10)), 7)
gtest.AssertIN(array1.Rands(1)[0], a1)
t.Assert(len(array1.Rands(2)), 2)
t.Assert(len(array1.Rands(10)), 7)
t.AssertIN(array1.Rands(1)[0], a1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []interface{}{"a", "b", "c", "d"}
a1 := garray.NewArrayFrom(s1)
i1 := a1.Rand()
gtest.Assert(a1.Contains(i1), true)
gtest.Assert(a1.Len(), 4)
t.Assert(a1.Contains(i1), true)
t.Assert(a1.Len(), 4)
})
}
func TestArray_Shuffle(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewArrayFrom(a1)
gtest.Assert(array1.Shuffle().Len(), 7)
t.Assert(array1.Shuffle().Len(), 7)
})
}
func TestArray_Reverse(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewArrayFrom(a1)
gtest.Assert(array1.Reverse().Slice(), []interface{}{6, 5, 4, 3, 2, 1, 0})
t.Assert(array1.Reverse().Slice(), []interface{}{6, 5, 4, 3, 2, 1, 0})
})
}
func TestArray_Join(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewArrayFrom(a1)
gtest.Assert(array1.Join("."), `0.1.2.3.4.5.6`)
t.Assert(array1.Join("."), `0.1.2.3.4.5.6`)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{0, 1, `"a"`, `\a`}
array1 := garray.NewArrayFrom(a1)
gtest.Assert(array1.Join("."), `0.1."a".\a`)
t.Assert(array1.Join("."), `0.1."a".\a`)
})
}
func TestArray_String(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewArrayFrom(a1)
gtest.Assert(array1.String(), `[0,1,2,3,4,5,6]`)
t.Assert(array1.String(), `[0,1,2,3,4,5,6]`)
})
}
func TestArray_Replace(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{0, 1, 2, 3, 4, 5, 6}
a2 := []interface{}{"a", "b", "c"}
a3 := []interface{}{"m", "n", "p", "z", "x", "y", "d", "u"}
array1 := garray.NewArrayFrom(a1)
array2 := array1.Replace(a2)
gtest.Assert(array2.Len(), 7)
gtest.Assert(array2.Contains("b"), true)
gtest.Assert(array2.Contains(4), true)
gtest.Assert(array2.Contains("v"), false)
t.Assert(array2.Len(), 7)
t.Assert(array2.Contains("b"), true)
t.Assert(array2.Contains(4), true)
t.Assert(array2.Contains("v"), false)
array3 := array1.Replace(a3)
gtest.Assert(array3.Len(), 7)
gtest.Assert(array3.Contains(4), false)
gtest.Assert(array3.Contains("p"), true)
gtest.Assert(array3.Contains("u"), false)
t.Assert(array3.Len(), 7)
t.Assert(array3.Contains(4), false)
t.Assert(array3.Contains("p"), true)
t.Assert(array3.Contains("u"), false)
})
}
func TestArray_SetArray(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{0, 1, 2, 3, 4, 5, 6}
a2 := []interface{}{"a", "b", "c"}
array1 := garray.NewArrayFrom(a1)
array1 = array1.SetArray(a2)
gtest.Assert(array1.Len(), 3)
gtest.Assert(array1.Contains("b"), true)
gtest.Assert(array1.Contains("5"), false)
t.Assert(array1.Len(), 3)
t.Assert(array1.Contains("b"), true)
t.Assert(array1.Contains("5"), false)
})
}
func TestArray_Sum(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{0, 1, 2, 3}
a2 := []interface{}{"a", "b", "c"}
a3 := []interface{}{"a", "1", "2"}
@ -346,39 +356,39 @@ func TestArray_Sum(t *testing.T) {
array2 := garray.NewArrayFrom(a2)
array3 := garray.NewArrayFrom(a3)
gtest.Assert(array1.Sum(), 6)
gtest.Assert(array2.Sum(), 0)
gtest.Assert(array3.Sum(), 3)
t.Assert(array1.Sum(), 6)
t.Assert(array2.Sum(), 0)
t.Assert(array3.Sum(), 3)
})
}
func TestArray_Clone(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{0, 1, 2, 3}
array1 := garray.NewArrayFrom(a1)
array2 := array1.Clone()
gtest.Assert(array1.Len(), 4)
gtest.Assert(array2.Sum(), 6)
gtest.AssertEQ(array1, array2)
t.Assert(array1.Len(), 4)
t.Assert(array2.Sum(), 6)
t.AssertEQ(array1, array2)
})
}
func TestArray_CountValues(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "b", "c", "d", "e", "d"}
array1 := garray.NewArrayFrom(a1)
array2 := array1.CountValues()
gtest.Assert(len(array2), 5)
gtest.Assert(array2["b"], 1)
gtest.Assert(array2["d"], 2)
t.Assert(len(array2), 5)
t.Assert(array2["b"], 1)
t.Assert(array2["d"], 2)
})
}
func TestArray_LockFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []interface{}{"a", "b", "c", "d"}
a1 := garray.NewArrayFrom(s1, true)
@ -404,13 +414,13 @@ func TestArray_LockFunc(t *testing.T) {
<-ch2 //等待go1完成
// 防止ci抖动,以豪秒为单位
gtest.AssertGT(t2-t1, 20) //go1加的读写互斥锁所go2读的时候被阻塞。
gtest.Assert(a1.Contains("g"), true)
t.AssertGT(t2-t1, 20) //go1加的读写互斥锁所go2读的时候被阻塞。
t.Assert(a1.Contains("g"), true)
})
}
func TestArray_RLockFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []interface{}{"a", "b", "c", "d"}
a1 := garray.NewArrayFrom(s1, true)
@ -436,32 +446,32 @@ func TestArray_RLockFunc(t *testing.T) {
<-ch2 //等待go1完成
// 防止ci抖动,以豪秒为单位
gtest.AssertLT(t2-t1, 20) //go1加的读锁所go2读的时候并没有阻塞。
gtest.Assert(a1.Contains("g"), true)
t.AssertLT(t2-t1, 20) //go1加的读锁所go2读的时候并没有阻塞。
t.Assert(a1.Contains("g"), true)
})
}
func TestArray_Json(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []interface{}{"a", "b", "d", "c"}
a1 := garray.NewArrayFrom(s1)
b1, err1 := json.Marshal(a1)
b2, err2 := json.Marshal(s1)
gtest.Assert(b1, b2)
gtest.Assert(err1, err2)
t.Assert(b1, b2)
t.Assert(err1, err2)
a2 := garray.New()
err2 = json.Unmarshal(b2, &a2)
gtest.Assert(err2, nil)
gtest.Assert(a2.Slice(), s1)
t.Assert(err2, nil)
t.Assert(a2.Slice(), s1)
var a3 garray.Array
err := json.Unmarshal(b2, &a3)
gtest.Assert(err, nil)
gtest.Assert(a3.Slice(), s1)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
type User struct {
Name string
Scores *garray.Array
@ -471,123 +481,123 @@ func TestArray_Json(t *testing.T) {
"Scores": []int{99, 100, 98},
}
b, err := json.Marshal(data)
gtest.Assert(err, nil)
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
gtest.Assert(err, nil)
gtest.Assert(user.Name, data["Name"])
gtest.Assert(user.Scores, data["Scores"])
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.Assert(user.Scores, data["Scores"])
})
}
func TestArray_Iterator(t *testing.T) {
slice := g.Slice{"a", "b", "d", "c"}
array := garray.NewArrayFrom(slice)
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.Iterator(func(k int, v interface{}) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.IteratorAsc(func(k int, v interface{}) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.IteratorDesc(func(k int, v interface{}) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.Iterator(func(k int, v interface{}) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.IteratorAsc(func(k int, v interface{}) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.IteratorDesc(func(k int, v interface{}) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
}
func TestArray_RemoveValue(t *testing.T) {
slice := g.Slice{"a", "b", "d", "c"}
array := garray.NewArrayFrom(slice)
gtest.Case(t, func() {
gtest.Assert(array.RemoveValue("e"), false)
gtest.Assert(array.RemoveValue("b"), true)
gtest.Assert(array.RemoveValue("a"), true)
gtest.Assert(array.RemoveValue("c"), true)
gtest.Assert(array.RemoveValue("f"), false)
gtest.C(t, func(t *gtest.T) {
t.Assert(array.RemoveValue("e"), false)
t.Assert(array.RemoveValue("b"), true)
t.Assert(array.RemoveValue("a"), true)
t.Assert(array.RemoveValue("c"), true)
t.Assert(array.RemoveValue("f"), false)
})
}
func TestArray_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Array *garray.Array
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": []byte(`[1,2,3]`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3})
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Array.Slice(), g.Slice{1, 2, 3})
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": g.Slice{1, 2, 3},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3})
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Array.Slice(), g.Slice{1, 2, 3})
})
}
func TestArray_FilterNil(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
values := g.Slice{0, 1, 2, 3, 4, "", g.Slice{}}
array := garray.NewArrayFromCopy(values)
gtest.Assert(array.FilterNil().Slice(), values)
t.Assert(array.FilterNil().Slice(), values)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array := garray.NewArrayFromCopy(g.Slice{nil, 1, 2, 3, 4, nil})
gtest.Assert(array.FilterNil(), g.Slice{1, 2, 3, 4})
t.Assert(array.FilterNil(), g.Slice{1, 2, 3, 4})
})
}
func TestArray_FilterEmpty(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array := garray.NewArrayFrom(g.Slice{0, 1, 2, 3, 4, "", g.Slice{}})
gtest.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4})
t.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array := garray.NewArrayFrom(g.Slice{1, 2, 3, 4})
gtest.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4})
t.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4})
})
}

View File

@ -21,37 +21,37 @@ import (
)
func Test_IntArray_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
expect := []int{0, 1, 2, 3}
expect2 := []int{}
array := garray.NewIntArrayFrom(expect)
array2 := garray.NewIntArrayFrom(expect2)
gtest.Assert(array.Slice(), expect)
gtest.Assert(array.Interfaces(), expect)
t.Assert(array.Slice(), expect)
t.Assert(array.Interfaces(), expect)
array.Set(0, 100)
gtest.Assert(array.Get(0), 100)
gtest.Assert(array.Get(1), 1)
gtest.Assert(array.Search(100), 0)
gtest.Assert(array2.Search(100), -1)
gtest.Assert(array.Contains(100), true)
gtest.Assert(array.Remove(0), 100)
gtest.Assert(array.Remove(-1), 0)
gtest.Assert(array.Remove(100000), 0)
gtest.Assert(array.Contains(100), false)
t.Assert(array.Get(0), 100)
t.Assert(array.Get(1), 1)
t.Assert(array.Search(100), 0)
t.Assert(array2.Search(100), -1)
t.Assert(array.Contains(100), true)
t.Assert(array.Remove(0), 100)
t.Assert(array.Remove(-1), 0)
t.Assert(array.Remove(100000), 0)
t.Assert(array.Contains(100), false)
array.Append(4)
gtest.Assert(array.Len(), 4)
t.Assert(array.Len(), 4)
array.InsertBefore(0, 100)
array.InsertAfter(0, 200)
gtest.Assert(array.Slice(), []int{100, 200, 1, 2, 3, 4})
t.Assert(array.Slice(), []int{100, 200, 1, 2, 3, 4})
array.InsertBefore(5, 300)
array.InsertAfter(6, 400)
gtest.Assert(array.Slice(), []int{100, 200, 1, 2, 3, 300, 4, 400})
gtest.Assert(array.Clear().Len(), 0)
t.Assert(array.Slice(), []int{100, 200, 1, 2, 3, 300, 4, 400})
t.Assert(array.Clear().Len(), 0)
})
}
func TestIntArray_Sort(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
expect1 := []int{0, 1, 2, 3}
expect2 := []int{3, 2, 1, 0}
array := garray.NewIntArray()
@ -61,69 +61,79 @@ func TestIntArray_Sort(t *testing.T) {
array2.Append(i)
}
array.Sort()
gtest.Assert(array.Slice(), expect1)
t.Assert(array.Slice(), expect1)
array.Sort(true)
gtest.Assert(array.Slice(), expect2)
gtest.Assert(array2.Slice(), expect2)
t.Assert(array.Slice(), expect2)
t.Assert(array2.Slice(), expect2)
})
}
func TestIntArray_Unique(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
expect := []int{1, 1, 2, 3}
array := garray.NewIntArrayFrom(expect)
gtest.Assert(array.Unique().Slice(), []int{1, 2, 3})
t.Assert(array.Unique().Slice(), []int{1, 2, 3})
})
}
func TestIntArray_PushAndPop(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
expect := []int{0, 1, 2, 3}
array := garray.NewIntArrayFrom(expect)
gtest.Assert(array.Slice(), expect)
gtest.Assert(array.PopLeft(), 0)
gtest.Assert(array.PopRight(), 3)
gtest.AssertIN(array.PopRand(), []int{1, 2})
gtest.AssertIN(array.PopRand(), []int{1, 2})
gtest.Assert(array.Len(), 0)
t.Assert(array.Slice(), expect)
t.Assert(array.PopLeft(), 0)
t.Assert(array.PopRight(), 3)
t.AssertIN(array.PopRand(), []int{1, 2})
t.AssertIN(array.PopRand(), []int{1, 2})
t.Assert(array.Len(), 0)
array.PushLeft(1).PushRight(2)
gtest.Assert(array.Slice(), []int{1, 2})
t.Assert(array.Slice(), []int{1, 2})
})
}
func TestIntArray_PopLeftsAndPopRights(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array := garray.NewIntArray()
t.Assert(array.PopLeft(), 0)
t.Assert(array.PopLefts(10), nil)
t.Assert(array.PopRight(), 0)
t.Assert(array.PopRights(10), nil)
t.Assert(array.PopRand(), 0)
t.Assert(array.PopRands(10), nil)
})
gtest.C(t, func(t *gtest.T) {
value1 := []int{0, 1, 2, 3, 4, 5, 6}
value2 := []int{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewIntArrayFrom(value1)
array2 := garray.NewIntArrayFrom(value2)
gtest.Assert(array1.PopLefts(2), []int{0, 1})
gtest.Assert(array1.Slice(), []int{2, 3, 4, 5, 6})
gtest.Assert(array1.PopRights(2), []int{5, 6})
gtest.Assert(array1.Slice(), []int{2, 3, 4})
gtest.Assert(array1.PopRights(20), []int{2, 3, 4})
gtest.Assert(array1.Slice(), []int{})
gtest.Assert(array2.PopLefts(20), []int{0, 1, 2, 3, 4, 5, 6})
gtest.Assert(array2.Slice(), []int{})
t.Assert(array1.PopLefts(2), []int{0, 1})
t.Assert(array1.Slice(), []int{2, 3, 4, 5, 6})
t.Assert(array1.PopRights(2), []int{5, 6})
t.Assert(array1.Slice(), []int{2, 3, 4})
t.Assert(array1.PopRights(20), []int{2, 3, 4})
t.Assert(array1.Slice(), []int{})
t.Assert(array2.PopLefts(20), []int{0, 1, 2, 3, 4, 5, 6})
t.Assert(array2.Slice(), []int{})
})
}
func TestIntArray_Range(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
value1 := []int{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewIntArrayFrom(value1)
array2 := garray.NewIntArrayFrom(value1, true)
gtest.Assert(array1.Range(0, 1), []int{0})
gtest.Assert(array1.Range(1, 2), []int{1})
gtest.Assert(array1.Range(0, 2), []int{0, 1})
gtest.Assert(array1.Range(10, 2), nil)
gtest.Assert(array1.Range(-1, 10), value1)
gtest.Assert(array2.Range(1, 2), []int{1})
t.Assert(array1.Range(0, 1), []int{0})
t.Assert(array1.Range(1, 2), []int{1})
t.Assert(array1.Range(0, 2), []int{0, 1})
t.Assert(array1.Range(10, 2), nil)
t.Assert(array1.Range(-1, 10), value1)
t.Assert(array2.Range(1, 2), []int{1})
})
}
func TestIntArray_Merge(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
func1 := func(v1, v2 interface{}) int {
if gconv.Int(v1) < gconv.Int(v2) {
return 0
@ -147,260 +157,260 @@ func TestIntArray_Merge(t *testing.T) {
a7 := garray.NewSortedStrArrayFrom(s1)
a8 := garray.NewSortedArrayFrom([]interface{}{4, 5}, func1)
gtest.Assert(a1.Merge(a2).Slice(), []int{0, 1, 2, 3, 4, 5, 6, 7})
gtest.Assert(a1.Merge(a3).Len(), 10)
gtest.Assert(a1.Merge(a4).Len(), 13)
gtest.Assert(a1.Merge(a5).Len(), 15)
gtest.Assert(a1.Merge(a6).Len(), 18)
gtest.Assert(a1.Merge(a7).Len(), 21)
gtest.Assert(a1.Merge(a8).Len(), 23)
t.Assert(a1.Merge(a2).Slice(), []int{0, 1, 2, 3, 4, 5, 6, 7})
t.Assert(a1.Merge(a3).Len(), 10)
t.Assert(a1.Merge(a4).Len(), 13)
t.Assert(a1.Merge(a5).Len(), 15)
t.Assert(a1.Merge(a6).Len(), 18)
t.Assert(a1.Merge(a7).Len(), 21)
t.Assert(a1.Merge(a8).Len(), 23)
})
}
func TestIntArray_Fill(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0}
a2 := []int{0}
array1 := garray.NewIntArrayFrom(a1)
array2 := garray.NewIntArrayFrom(a2)
gtest.Assert(array1.Fill(1, 2, 100).Slice(), []int{0, 100, 100})
gtest.Assert(array2.Fill(0, 2, 100).Slice(), []int{100, 100})
gtest.Assert(array2.Fill(-1, 2, 100).Slice(), []int{100, 100})
t.Assert(array1.Fill(1, 2, 100).Slice(), []int{0, 100, 100})
t.Assert(array2.Fill(0, 2, 100).Slice(), []int{100, 100})
t.Assert(array2.Fill(-1, 2, 100).Slice(), []int{100, 100})
})
}
func TestIntArray_Chunk(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5}
array1 := garray.NewIntArrayFrom(a1)
chunks := array1.Chunk(2)
gtest.Assert(len(chunks), 3)
gtest.Assert(chunks[0], []int{1, 2})
gtest.Assert(chunks[1], []int{3, 4})
gtest.Assert(chunks[2], []int{5})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 3)
t.Assert(chunks[0], []int{1, 2})
t.Assert(chunks[1], []int{3, 4})
t.Assert(chunks[2], []int{5})
t.Assert(array1.Chunk(0), nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5}
array1 := garray.NewIntArrayFrom(a1)
chunks := array1.Chunk(3)
gtest.Assert(len(chunks), 2)
gtest.Assert(chunks[0], []int{1, 2, 3})
gtest.Assert(chunks[1], []int{4, 5})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 2)
t.Assert(chunks[0], []int{1, 2, 3})
t.Assert(chunks[1], []int{4, 5})
t.Assert(array1.Chunk(0), nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5, 6}
array1 := garray.NewIntArrayFrom(a1)
chunks := array1.Chunk(2)
gtest.Assert(len(chunks), 3)
gtest.Assert(chunks[0], []int{1, 2})
gtest.Assert(chunks[1], []int{3, 4})
gtest.Assert(chunks[2], []int{5, 6})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 3)
t.Assert(chunks[0], []int{1, 2})
t.Assert(chunks[1], []int{3, 4})
t.Assert(chunks[2], []int{5, 6})
t.Assert(array1.Chunk(0), nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5, 6}
array1 := garray.NewIntArrayFrom(a1)
chunks := array1.Chunk(3)
gtest.Assert(len(chunks), 2)
gtest.Assert(chunks[0], []int{1, 2, 3})
gtest.Assert(chunks[1], []int{4, 5, 6})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 2)
t.Assert(chunks[0], []int{1, 2, 3})
t.Assert(chunks[1], []int{4, 5, 6})
t.Assert(array1.Chunk(0), nil)
})
}
func TestIntArray_Pad(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0}
array1 := garray.NewIntArrayFrom(a1)
gtest.Assert(array1.Pad(3, 1).Slice(), []int{0, 1, 1})
gtest.Assert(array1.Pad(-4, 1).Slice(), []int{1, 0, 1, 1})
gtest.Assert(array1.Pad(3, 1).Slice(), []int{1, 0, 1, 1})
t.Assert(array1.Pad(3, 1).Slice(), []int{0, 1, 1})
t.Assert(array1.Pad(-4, 1).Slice(), []int{1, 0, 1, 1})
t.Assert(array1.Pad(3, 1).Slice(), []int{1, 0, 1, 1})
})
}
func TestIntArray_SubSlice(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewIntArrayFrom(a1)
array2 := garray.NewIntArrayFrom(a1, true)
gtest.Assert(array1.SubSlice(6), []int{6})
gtest.Assert(array1.SubSlice(5), []int{5, 6})
gtest.Assert(array1.SubSlice(8), nil)
gtest.Assert(array1.SubSlice(0, 2), []int{0, 1})
gtest.Assert(array1.SubSlice(2, 2), []int{2, 3})
gtest.Assert(array1.SubSlice(5, 8), []int{5, 6})
gtest.Assert(array1.SubSlice(-1, 1), []int{6})
gtest.Assert(array1.SubSlice(-1, 9), []int{6})
gtest.Assert(array1.SubSlice(-2, 3), []int{5, 6})
gtest.Assert(array1.SubSlice(-7, 3), []int{0, 1, 2})
gtest.Assert(array1.SubSlice(-8, 3), nil)
gtest.Assert(array1.SubSlice(-1, -3), []int{3, 4, 5})
gtest.Assert(array1.SubSlice(-9, 3), nil)
gtest.Assert(array1.SubSlice(1, -1), []int{0})
gtest.Assert(array1.SubSlice(1, -3), nil)
gtest.Assert(array2.SubSlice(0, 2), []int{0, 1})
t.Assert(array1.SubSlice(6), []int{6})
t.Assert(array1.SubSlice(5), []int{5, 6})
t.Assert(array1.SubSlice(8), nil)
t.Assert(array1.SubSlice(0, 2), []int{0, 1})
t.Assert(array1.SubSlice(2, 2), []int{2, 3})
t.Assert(array1.SubSlice(5, 8), []int{5, 6})
t.Assert(array1.SubSlice(-1, 1), []int{6})
t.Assert(array1.SubSlice(-1, 9), []int{6})
t.Assert(array1.SubSlice(-2, 3), []int{5, 6})
t.Assert(array1.SubSlice(-7, 3), []int{0, 1, 2})
t.Assert(array1.SubSlice(-8, 3), nil)
t.Assert(array1.SubSlice(-1, -3), []int{3, 4, 5})
t.Assert(array1.SubSlice(-9, 3), nil)
t.Assert(array1.SubSlice(1, -1), []int{0})
t.Assert(array1.SubSlice(1, -3), nil)
t.Assert(array2.SubSlice(0, 2), []int{0, 1})
})
}
func TestIntArray_Rand(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewIntArrayFrom(a1)
gtest.Assert(len(array1.Rands(2)), 2)
gtest.Assert(len(array1.Rands(10)), 7)
gtest.AssertIN(array1.Rands(1)[0], a1)
gtest.AssertIN(array1.Rand(), a1)
t.Assert(len(array1.Rands(2)), 2)
t.Assert(len(array1.Rands(10)), 7)
t.AssertIN(array1.Rands(1)[0], a1)
t.AssertIN(array1.Rand(), a1)
})
}
func TestIntArray_PopRands(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{100, 200, 300, 400, 500, 600}
array := garray.NewIntArrayFrom(a1)
ns1 := array.PopRands(2)
gtest.AssertIN(ns1, []int{100, 200, 300, 400, 500, 600})
gtest.Assert(len(ns1), 2)
t.AssertIN(ns1, []int{100, 200, 300, 400, 500, 600})
t.Assert(len(ns1), 2)
ns2 := array.PopRands(7)
gtest.Assert(len(ns2), 4)
gtest.AssertIN(ns2, []int{100, 200, 300, 400, 500, 600})
t.Assert(len(ns2), 4)
t.AssertIN(ns2, []int{100, 200, 300, 400, 500, 600})
})
}
func TestIntArray_Shuffle(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewIntArrayFrom(a1)
gtest.Assert(array1.Shuffle().Len(), 7)
t.Assert(array1.Shuffle().Len(), 7)
})
}
func TestIntArray_Reverse(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewIntArrayFrom(a1)
gtest.Assert(array1.Reverse().Slice(), []int{6, 5, 4, 3, 2, 1, 0})
t.Assert(array1.Reverse().Slice(), []int{6, 5, 4, 3, 2, 1, 0})
})
}
func TestIntArray_Join(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewIntArrayFrom(a1)
gtest.Assert(array1.Join("."), "0.1.2.3.4.5.6")
t.Assert(array1.Join("."), "0.1.2.3.4.5.6")
})
}
func TestIntArray_String(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 1, 2, 3, 4, 5, 6}
array1 := garray.NewIntArrayFrom(a1)
gtest.Assert(array1.String(), "[0,1,2,3,4,5,6]")
t.Assert(array1.String(), "[0,1,2,3,4,5,6]")
})
}
func TestIntArray_SetArray(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 5}
a2 := []int{6, 7}
array1 := garray.NewIntArrayFrom(a1)
array1.SetArray(a2)
gtest.Assert(array1.Len(), 2)
gtest.Assert(array1, []int{6, 7})
t.Assert(array1.Len(), 2)
t.Assert(array1, []int{6, 7})
})
}
func TestIntArray_Replace(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 5}
a2 := []int{6, 7}
a3 := []int{9, 10, 11, 12, 13}
array1 := garray.NewIntArrayFrom(a1)
array1.Replace(a2)
gtest.Assert(array1, []int{6, 7, 3, 5})
t.Assert(array1, []int{6, 7, 3, 5})
array1.Replace(a3)
gtest.Assert(array1, []int{9, 10, 11, 12})
t.Assert(array1, []int{9, 10, 11, 12})
})
}
func TestIntArray_Clear(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 5}
array1 := garray.NewIntArrayFrom(a1)
array1.Clear()
gtest.Assert(array1.Len(), 0)
t.Assert(array1.Len(), 0)
})
}
func TestIntArray_Clone(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 5}
array1 := garray.NewIntArrayFrom(a1)
array2 := array1.Clone()
gtest.Assert(array1, array2)
t.Assert(array1, array2)
})
}
func TestArray_Get(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 5}
array1 := garray.NewIntArrayFrom(a1)
gtest.Assert(array1.Get(2), 3)
gtest.Assert(array1.Len(), 4)
t.Assert(array1.Get(2), 3)
t.Assert(array1.Len(), 4)
})
}
func TestIntArray_Sum(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 5}
array1 := garray.NewIntArrayFrom(a1)
gtest.Assert(array1.Sum(), 11)
t.Assert(array1.Sum(), 11)
})
}
func TestIntArray_CountValues(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 5, 3}
array1 := garray.NewIntArrayFrom(a1)
m1 := array1.CountValues()
gtest.Assert(len(m1), 4)
gtest.Assert(m1[1], 1)
gtest.Assert(m1[3], 2)
t.Assert(len(m1), 4)
t.Assert(m1[1], 1)
t.Assert(m1[3], 2)
})
}
func TestNewIntArrayFromCopy(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 5, 3}
array1 := garray.NewIntArrayFromCopy(a1)
gtest.Assert(array1.Len(), 5)
gtest.Assert(array1, a1)
t.Assert(array1.Len(), 5)
t.Assert(array1, a1)
})
}
func TestIntArray_Remove(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 5, 4}
array1 := garray.NewIntArrayFrom(a1)
n1 := array1.Remove(1)
gtest.Assert(n1, 2)
gtest.Assert(array1.Len(), 4)
t.Assert(n1, 2)
t.Assert(array1.Len(), 4)
n1 = array1.Remove(0)
gtest.Assert(n1, 1)
gtest.Assert(array1.Len(), 3)
t.Assert(n1, 1)
t.Assert(array1.Len(), 3)
n1 = array1.Remove(2)
gtest.Assert(n1, 4)
gtest.Assert(array1.Len(), 2)
t.Assert(n1, 4)
t.Assert(array1.Len(), 2)
})
}
func TestIntArray_LockFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []int{1, 2, 3, 4}
a1 := garray.NewIntArrayFrom(s1, true)
@ -426,26 +436,26 @@ func TestIntArray_LockFunc(t *testing.T) {
<-ch2 //等待go1完成
// 防止ci抖动,以豪秒为单位
gtest.AssertGT(t2-t1, 20) //go1加的读写互斥锁所go2读的时候被阻塞。
gtest.Assert(a1.Contains(6), true)
t.AssertGT(t2-t1, 20) //go1加的读写互斥锁所go2读的时候被阻塞。
t.Assert(a1.Contains(6), true)
})
}
func TestIntArray_SortFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []int{1, 4, 3, 2}
a1 := garray.NewIntArrayFrom(s1)
func1 := func(v1, v2 int) bool {
return v1 < v2
}
a11 := a1.SortFunc(func1)
gtest.Assert(a11, []int{1, 2, 3, 4})
t.Assert(a11, []int{1, 2, 3, 4})
})
}
func TestIntArray_RLockFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []int{1, 2, 3, 4}
a1 := garray.NewIntArrayFrom(s1, true)
@ -471,31 +481,31 @@ func TestIntArray_RLockFunc(t *testing.T) {
<-ch2 //等待go1完成
// 防止ci抖动,以豪秒为单位
gtest.AssertLT(t2-t1, 20) //go1加的读锁所go2读的时候并没有阻塞。
gtest.Assert(a1.Contains(6), true)
t.AssertLT(t2-t1, 20) //go1加的读锁所go2读的时候并没有阻塞。
t.Assert(a1.Contains(6), true)
})
}
func TestIntArray_Json(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []int{1, 4, 3, 2}
a1 := garray.NewIntArrayFrom(s1)
b1, err1 := json.Marshal(a1)
b2, err2 := json.Marshal(s1)
gtest.Assert(b1, b2)
gtest.Assert(err1, err2)
t.Assert(b1, b2)
t.Assert(err1, err2)
a2 := garray.NewIntArray()
err1 = json.Unmarshal(b2, &a2)
gtest.Assert(a2.Slice(), s1)
t.Assert(a2.Slice(), s1)
var a3 garray.IntArray
err := json.Unmarshal(b2, &a3)
gtest.Assert(err, nil)
gtest.Assert(a3.Slice(), s1)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
type User struct {
Name string
Scores *garray.IntArray
@ -505,112 +515,112 @@ func TestIntArray_Json(t *testing.T) {
"Scores": []int{99, 100, 98},
}
b, err := json.Marshal(data)
gtest.Assert(err, nil)
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
gtest.Assert(err, nil)
gtest.Assert(user.Name, data["Name"])
gtest.Assert(user.Scores, data["Scores"])
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.Assert(user.Scores, data["Scores"])
})
}
func TestIntArray_Iterator(t *testing.T) {
slice := g.SliceInt{10, 20, 30, 40}
array := garray.NewIntArrayFrom(slice)
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.Iterator(func(k int, v int) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.IteratorAsc(func(k int, v int) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.IteratorDesc(func(k int, v int) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.Iterator(func(k int, v int) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.IteratorAsc(func(k int, v int) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.IteratorDesc(func(k int, v int) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
}
func TestIntArray_RemoveValue(t *testing.T) {
slice := g.SliceInt{10, 20, 30, 40}
array := garray.NewIntArrayFrom(slice)
gtest.Case(t, func() {
gtest.Assert(array.RemoveValue(99), false)
gtest.Assert(array.RemoveValue(20), true)
gtest.Assert(array.RemoveValue(10), true)
gtest.Assert(array.RemoveValue(20), false)
gtest.Assert(array.RemoveValue(88), false)
gtest.Assert(array.Len(), 2)
gtest.C(t, func(t *gtest.T) {
t.Assert(array.RemoveValue(99), false)
t.Assert(array.RemoveValue(20), true)
t.Assert(array.RemoveValue(10), true)
t.Assert(array.RemoveValue(20), false)
t.Assert(array.RemoveValue(88), false)
t.Assert(array.Len(), 2)
})
}
func TestIntArray_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Array *garray.IntArray
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": []byte(`[1,2,3]`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3})
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Array.Slice(), g.Slice{1, 2, 3})
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": g.Slice{1, 2, 3},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3})
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Array.Slice(), g.Slice{1, 2, 3})
})
}
func TestIntArray_FilterEmpty(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array := garray.NewIntArrayFrom(g.SliceInt{0, 1, 2, 3, 4, 0})
gtest.Assert(array.FilterEmpty(), g.SliceInt{1, 2, 3, 4})
t.Assert(array.FilterEmpty(), g.SliceInt{1, 2, 3, 4})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array := garray.NewIntArrayFrom(g.SliceInt{1, 2, 3, 4})
gtest.Assert(array.FilterEmpty(), g.SliceInt{1, 2, 3, 4})
t.Assert(array.FilterEmpty(), g.SliceInt{1, 2, 3, 4})
})
}

View File

@ -21,38 +21,38 @@ import (
)
func Test_StrArray_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
expect := []string{"0", "1", "2", "3"}
array := garray.NewStrArrayFrom(expect)
array2 := garray.NewStrArrayFrom(expect, true)
array3 := garray.NewStrArrayFrom([]string{})
gtest.Assert(array.Slice(), expect)
gtest.Assert(array.Interfaces(), expect)
t.Assert(array.Slice(), expect)
t.Assert(array.Interfaces(), expect)
array.Set(0, "100")
gtest.Assert(array.Get(0), 100)
gtest.Assert(array.Get(1), 1)
gtest.Assert(array.Search("100"), 0)
gtest.Assert(array.Contains("100"), true)
gtest.Assert(array.Remove(0), 100)
gtest.Assert(array.Remove(-1), "")
gtest.Assert(array.Remove(100000), "")
gtest.Assert(array.Contains("100"), false)
t.Assert(array.Get(0), 100)
t.Assert(array.Get(1), 1)
t.Assert(array.Search("100"), 0)
t.Assert(array.Contains("100"), true)
t.Assert(array.Remove(0), 100)
t.Assert(array.Remove(-1), "")
t.Assert(array.Remove(100000), "")
t.Assert(array.Contains("100"), false)
array.Append("4")
gtest.Assert(array.Len(), 4)
t.Assert(array.Len(), 4)
array.InsertBefore(0, "100")
array.InsertAfter(0, "200")
gtest.Assert(array.Slice(), []string{"100", "200", "1", "2", "3", "4"})
t.Assert(array.Slice(), []string{"100", "200", "1", "2", "3", "4"})
array.InsertBefore(5, "300")
array.InsertAfter(6, "400")
gtest.Assert(array.Slice(), []string{"100", "200", "1", "2", "3", "300", "4", "400"})
gtest.Assert(array.Clear().Len(), 0)
gtest.Assert(array2.Slice(), expect)
gtest.Assert(array3.Search("100"), -1)
t.Assert(array.Slice(), []string{"100", "200", "1", "2", "3", "300", "4", "400"})
t.Assert(array.Clear().Len(), 0)
t.Assert(array2.Slice(), expect)
t.Assert(array3.Search("100"), -1)
})
}
func TestStrArray_Sort(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
expect1 := []string{"0", "1", "2", "3"}
expect2 := []string{"3", "2", "1", "0"}
array := garray.NewStrArray()
@ -60,73 +60,83 @@ func TestStrArray_Sort(t *testing.T) {
array.Append(gconv.String(i))
}
array.Sort()
gtest.Assert(array.Slice(), expect1)
t.Assert(array.Slice(), expect1)
array.Sort(true)
gtest.Assert(array.Slice(), expect2)
t.Assert(array.Slice(), expect2)
})
}
func TestStrArray_Unique(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
expect := []string{"1", "1", "2", "3"}
array := garray.NewStrArrayFrom(expect)
gtest.Assert(array.Unique().Slice(), []string{"1", "2", "3"})
t.Assert(array.Unique().Slice(), []string{"1", "2", "3"})
})
}
func TestStrArray_PushAndPop(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
expect := []string{"0", "1", "2", "3"}
array := garray.NewStrArrayFrom(expect)
gtest.Assert(array.Slice(), expect)
gtest.Assert(array.PopLeft(), "0")
gtest.Assert(array.PopRight(), "3")
gtest.AssertIN(array.PopRand(), []string{"1", "2"})
gtest.AssertIN(array.PopRand(), []string{"1", "2"})
gtest.Assert(array.Len(), 0)
t.Assert(array.Slice(), expect)
t.Assert(array.PopLeft(), "0")
t.Assert(array.PopRight(), "3")
t.AssertIN(array.PopRand(), []string{"1", "2"})
t.AssertIN(array.PopRand(), []string{"1", "2"})
t.Assert(array.Len(), 0)
array.PushLeft("1").PushRight("2")
gtest.Assert(array.Slice(), []string{"1", "2"})
t.Assert(array.Slice(), []string{"1", "2"})
})
}
func TestStrArray_PopLeftsAndPopRights(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array := garray.NewStrArray()
t.Assert(array.PopLeft(), nil)
t.Assert(array.PopLefts(10), nil)
t.Assert(array.PopRight(), nil)
t.Assert(array.PopRights(10), nil)
t.Assert(array.PopRand(), nil)
t.Assert(array.PopRands(10), nil)
})
gtest.C(t, func(t *gtest.T) {
value1 := []string{"0", "1", "2", "3", "4", "5", "6"}
value2 := []string{"0", "1", "2", "3", "4", "5", "6"}
array1 := garray.NewStrArrayFrom(value1)
array2 := garray.NewStrArrayFrom(value2)
gtest.Assert(array1.PopLefts(2), []interface{}{"0", "1"})
gtest.Assert(array1.Slice(), []interface{}{"2", "3", "4", "5", "6"})
gtest.Assert(array1.PopRights(2), []interface{}{"5", "6"})
gtest.Assert(array1.Slice(), []interface{}{"2", "3", "4"})
gtest.Assert(array1.PopRights(20), []interface{}{"2", "3", "4"})
gtest.Assert(array1.Slice(), []interface{}{})
gtest.Assert(array2.PopLefts(20), []interface{}{"0", "1", "2", "3", "4", "5", "6"})
gtest.Assert(array2.Slice(), []interface{}{})
t.Assert(array1.PopLefts(2), []interface{}{"0", "1"})
t.Assert(array1.Slice(), []interface{}{"2", "3", "4", "5", "6"})
t.Assert(array1.PopRights(2), []interface{}{"5", "6"})
t.Assert(array1.Slice(), []interface{}{"2", "3", "4"})
t.Assert(array1.PopRights(20), []interface{}{"2", "3", "4"})
t.Assert(array1.Slice(), []interface{}{})
t.Assert(array2.PopLefts(20), []interface{}{"0", "1", "2", "3", "4", "5", "6"})
t.Assert(array2.Slice(), []interface{}{})
})
}
func TestString_Range(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
value1 := []string{"0", "1", "2", "3", "4", "5", "6"}
array1 := garray.NewStrArrayFrom(value1)
array2 := garray.NewStrArrayFrom(value1, true)
gtest.Assert(array1.Range(0, 1), []interface{}{"0"})
gtest.Assert(array1.Range(1, 2), []interface{}{"1"})
gtest.Assert(array1.Range(0, 2), []interface{}{"0", "1"})
gtest.Assert(array1.Range(-1, 10), value1)
gtest.Assert(array1.Range(10, 1), nil)
gtest.Assert(array2.Range(0, 1), []interface{}{"0"})
t.Assert(array1.Range(0, 1), []interface{}{"0"})
t.Assert(array1.Range(1, 2), []interface{}{"1"})
t.Assert(array1.Range(0, 2), []interface{}{"0", "1"})
t.Assert(array1.Range(-1, 10), value1)
t.Assert(array1.Range(10, 1), nil)
t.Assert(array2.Range(0, 1), []interface{}{"0"})
})
}
func TestStrArray_Merge(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a11 := []string{"0", "1", "2", "3"}
a21 := []string{"4", "5", "6", "7"}
array1 := garray.NewStrArrayFrom(a11)
array2 := garray.NewStrArrayFrom(a21)
gtest.Assert(array1.Merge(array2).Slice(), []string{"0", "1", "2", "3", "4", "5", "6", "7"})
t.Assert(array1.Merge(array2).Slice(), []string{"0", "1", "2", "3", "4", "5", "6", "7"})
func1 := func(v1, v2 interface{}) int {
if gconv.Int(v1) < gconv.Int(v2) {
@ -145,267 +155,267 @@ func TestStrArray_Merge(t *testing.T) {
s6 := garray.NewSortedIntArrayFrom([]int{1, 2, 3})
a1 := garray.NewStrArrayFrom(s1)
gtest.Assert(a1.Merge(s2).Len(), 6)
gtest.Assert(a1.Merge(i1).Len(), 9)
gtest.Assert(a1.Merge(i2).Len(), 10)
gtest.Assert(a1.Merge(s3).Len(), 12)
gtest.Assert(a1.Merge(s4).Len(), 14)
gtest.Assert(a1.Merge(s5).Len(), 16)
gtest.Assert(a1.Merge(s6).Len(), 19)
t.Assert(a1.Merge(s2).Len(), 6)
t.Assert(a1.Merge(i1).Len(), 9)
t.Assert(a1.Merge(i2).Len(), 10)
t.Assert(a1.Merge(s3).Len(), 12)
t.Assert(a1.Merge(s4).Len(), 14)
t.Assert(a1.Merge(s5).Len(), 16)
t.Assert(a1.Merge(s6).Len(), 19)
})
}
func TestStrArray_Fill(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"0"}
a2 := []string{"0"}
array1 := garray.NewStrArrayFrom(a1)
array2 := garray.NewStrArrayFrom(a2)
gtest.Assert(array1.Fill(1, 2, "100").Slice(), []string{"0", "100", "100"})
gtest.Assert(array2.Fill(0, 2, "100").Slice(), []string{"100", "100"})
t.Assert(array1.Fill(1, 2, "100").Slice(), []string{"0", "100", "100"})
t.Assert(array2.Fill(0, 2, "100").Slice(), []string{"100", "100"})
s1 := array2.Fill(-1, 2, "100")
gtest.Assert(s1.Len(), 2)
t.Assert(s1.Len(), 2)
})
}
func TestStrArray_Chunk(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"1", "2", "3", "4", "5"}
array1 := garray.NewStrArrayFrom(a1)
chunks := array1.Chunk(2)
gtest.Assert(len(chunks), 3)
gtest.Assert(chunks[0], []string{"1", "2"})
gtest.Assert(chunks[1], []string{"3", "4"})
gtest.Assert(chunks[2], []string{"5"})
gtest.Assert(len(array1.Chunk(0)), 0)
t.Assert(len(chunks), 3)
t.Assert(chunks[0], []string{"1", "2"})
t.Assert(chunks[1], []string{"3", "4"})
t.Assert(chunks[2], []string{"5"})
t.Assert(len(array1.Chunk(0)), 0)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"1", "2", "3", "4", "5"}
array1 := garray.NewStrArrayFrom(a1)
chunks := array1.Chunk(3)
gtest.Assert(len(chunks), 2)
gtest.Assert(chunks[0], []string{"1", "2", "3"})
gtest.Assert(chunks[1], []string{"4", "5"})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 2)
t.Assert(chunks[0], []string{"1", "2", "3"})
t.Assert(chunks[1], []string{"4", "5"})
t.Assert(array1.Chunk(0), nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"1", "2", "3", "4", "5", "6"}
array1 := garray.NewStrArrayFrom(a1)
chunks := array1.Chunk(2)
gtest.Assert(len(chunks), 3)
gtest.Assert(chunks[0], []string{"1", "2"})
gtest.Assert(chunks[1], []string{"3", "4"})
gtest.Assert(chunks[2], []string{"5", "6"})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 3)
t.Assert(chunks[0], []string{"1", "2"})
t.Assert(chunks[1], []string{"3", "4"})
t.Assert(chunks[2], []string{"5", "6"})
t.Assert(array1.Chunk(0), nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"1", "2", "3", "4", "5", "6"}
array1 := garray.NewStrArrayFrom(a1)
chunks := array1.Chunk(3)
gtest.Assert(len(chunks), 2)
gtest.Assert(chunks[0], []string{"1", "2", "3"})
gtest.Assert(chunks[1], []string{"4", "5", "6"})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 2)
t.Assert(chunks[0], []string{"1", "2", "3"})
t.Assert(chunks[1], []string{"4", "5", "6"})
t.Assert(array1.Chunk(0), nil)
})
}
func TestStrArray_Pad(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"0"}
array1 := garray.NewStrArrayFrom(a1)
gtest.Assert(array1.Pad(3, "1").Slice(), []string{"0", "1", "1"})
gtest.Assert(array1.Pad(-4, "1").Slice(), []string{"1", "0", "1", "1"})
gtest.Assert(array1.Pad(3, "1").Slice(), []string{"1", "0", "1", "1"})
t.Assert(array1.Pad(3, "1").Slice(), []string{"0", "1", "1"})
t.Assert(array1.Pad(-4, "1").Slice(), []string{"1", "0", "1", "1"})
t.Assert(array1.Pad(3, "1").Slice(), []string{"1", "0", "1", "1"})
})
}
func TestStrArray_SubSlice(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"0", "1", "2", "3", "4", "5", "6"}
array1 := garray.NewStrArrayFrom(a1)
array2 := garray.NewStrArrayFrom(a1, true)
gtest.Assert(array1.SubSlice(0, 2), []string{"0", "1"})
gtest.Assert(array1.SubSlice(2, 2), []string{"2", "3"})
gtest.Assert(array1.SubSlice(5, 8), []string{"5", "6"})
gtest.Assert(array1.SubSlice(8, 2), nil)
gtest.Assert(array1.SubSlice(1, -2), nil)
gtest.Assert(array1.SubSlice(-5, 2), []string{"2", "3"})
gtest.Assert(array1.SubSlice(-10, 1), nil)
gtest.Assert(array2.SubSlice(0, 2), []string{"0", "1"})
t.Assert(array1.SubSlice(0, 2), []string{"0", "1"})
t.Assert(array1.SubSlice(2, 2), []string{"2", "3"})
t.Assert(array1.SubSlice(5, 8), []string{"5", "6"})
t.Assert(array1.SubSlice(8, 2), nil)
t.Assert(array1.SubSlice(1, -2), nil)
t.Assert(array1.SubSlice(-5, 2), []string{"2", "3"})
t.Assert(array1.SubSlice(-10, 1), nil)
t.Assert(array2.SubSlice(0, 2), []string{"0", "1"})
})
}
func TestStrArray_Rand(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"0", "1", "2", "3", "4", "5", "6"}
array1 := garray.NewStrArrayFrom(a1)
gtest.Assert(len(array1.Rands(2)), "2")
gtest.Assert(len(array1.Rands(10)), "7")
gtest.AssertIN(array1.Rands(1)[0], a1)
gtest.Assert(len(array1.Rand()), 1)
gtest.AssertIN(array1.Rand(), a1)
t.Assert(len(array1.Rands(2)), "2")
t.Assert(len(array1.Rands(10)), "7")
t.AssertIN(array1.Rands(1)[0], a1)
t.Assert(len(array1.Rand()), 1)
t.AssertIN(array1.Rand(), a1)
})
}
func TestStrArray_PopRands(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"a", "b", "c", "d", "e", "f", "g"}
array1 := garray.NewStrArrayFrom(a1)
gtest.AssertIN(array1.PopRands(1), []string{"a", "b", "c", "d", "e", "f", "g"})
gtest.AssertIN(array1.PopRands(1), []string{"a", "b", "c", "d", "e", "f", "g"})
gtest.AssertNI(array1.PopRands(1), array1.Slice())
gtest.AssertNI(array1.PopRands(1), array1.Slice())
gtest.Assert(len(array1.PopRands(10)), 3)
t.AssertIN(array1.PopRands(1), []string{"a", "b", "c", "d", "e", "f", "g"})
t.AssertIN(array1.PopRands(1), []string{"a", "b", "c", "d", "e", "f", "g"})
t.AssertNI(array1.PopRands(1), array1.Slice())
t.AssertNI(array1.PopRands(1), array1.Slice())
t.Assert(len(array1.PopRands(10)), 3)
})
}
func TestStrArray_Shuffle(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"0", "1", "2", "3", "4", "5", "6"}
array1 := garray.NewStrArrayFrom(a1)
gtest.Assert(array1.Shuffle().Len(), 7)
t.Assert(array1.Shuffle().Len(), 7)
})
}
func TestStrArray_Reverse(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"0", "1", "2", "3", "4", "5", "6"}
array1 := garray.NewStrArrayFrom(a1)
gtest.Assert(array1.Reverse().Slice(), []string{"6", "5", "4", "3", "2", "1", "0"})
t.Assert(array1.Reverse().Slice(), []string{"6", "5", "4", "3", "2", "1", "0"})
})
}
func TestStrArray_Join(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"0", "1", "2", "3", "4", "5", "6"}
array1 := garray.NewStrArrayFrom(a1)
gtest.Assert(array1.Join("."), `0.1.2.3.4.5.6`)
t.Assert(array1.Join("."), `0.1.2.3.4.5.6`)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"0", "1", `"a"`, `\a`}
array1 := garray.NewStrArrayFrom(a1)
gtest.Assert(array1.Join("."), `0.1."a".\a`)
t.Assert(array1.Join("."), `0.1."a".\a`)
})
}
func TestStrArray_String(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"0", "1", "2", "3", "4", "5", "6"}
array1 := garray.NewStrArrayFrom(a1)
gtest.Assert(array1.String(), `["0","1","2","3","4","5","6"]`)
t.Assert(array1.String(), `["0","1","2","3","4","5","6"]`)
})
}
func TestNewStrArrayFromCopy(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"0", "1", "2", "3", "4", "5", "6"}
a2 := garray.NewStrArrayFromCopy(a1)
a3 := garray.NewStrArrayFromCopy(a1, true)
gtest.Assert(a2.Contains("1"), true)
gtest.Assert(a2.Len(), 7)
gtest.Assert(a2, a3)
t.Assert(a2.Contains("1"), true)
t.Assert(a2.Len(), 7)
t.Assert(a2, a3)
})
}
func TestStrArray_SetArray(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"0", "1", "2", "3", "4", "5", "6"}
a2 := []string{"a", "b", "c", "d"}
array1 := garray.NewStrArrayFrom(a1)
gtest.Assert(array1.Contains("2"), true)
gtest.Assert(array1.Len(), 7)
t.Assert(array1.Contains("2"), true)
t.Assert(array1.Len(), 7)
array1 = array1.SetArray(a2)
gtest.Assert(array1.Contains("2"), false)
gtest.Assert(array1.Contains("c"), true)
gtest.Assert(array1.Len(), 4)
t.Assert(array1.Contains("2"), false)
t.Assert(array1.Contains("c"), true)
t.Assert(array1.Len(), 4)
})
}
func TestStrArray_Replace(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"0", "1", "2", "3", "4", "5", "6"}
a2 := []string{"a", "b", "c", "d"}
a3 := []string{"o", "p", "q", "x", "y", "z", "w", "r", "v"}
array1 := garray.NewStrArrayFrom(a1)
gtest.Assert(array1.Contains("2"), true)
gtest.Assert(array1.Len(), 7)
t.Assert(array1.Contains("2"), true)
t.Assert(array1.Len(), 7)
array1 = array1.Replace(a2)
gtest.Assert(array1.Contains("2"), false)
gtest.Assert(array1.Contains("c"), true)
gtest.Assert(array1.Contains("5"), true)
gtest.Assert(array1.Len(), 7)
t.Assert(array1.Contains("2"), false)
t.Assert(array1.Contains("c"), true)
t.Assert(array1.Contains("5"), true)
t.Assert(array1.Len(), 7)
array1 = array1.Replace(a3)
gtest.Assert(array1.Contains("2"), false)
gtest.Assert(array1.Contains("c"), false)
gtest.Assert(array1.Contains("5"), false)
gtest.Assert(array1.Contains("p"), true)
gtest.Assert(array1.Contains("r"), false)
gtest.Assert(array1.Len(), 7)
t.Assert(array1.Contains("2"), false)
t.Assert(array1.Contains("c"), false)
t.Assert(array1.Contains("5"), false)
t.Assert(array1.Contains("p"), true)
t.Assert(array1.Contains("r"), false)
t.Assert(array1.Len(), 7)
})
}
func TestStrArray_Sum(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"0", "1", "2", "3", "4", "5", "6"}
a2 := []string{"0", "a", "3", "4", "5", "6"}
array1 := garray.NewStrArrayFrom(a1)
array2 := garray.NewStrArrayFrom(a2)
gtest.Assert(array1.Sum(), 21)
gtest.Assert(array2.Sum(), 18)
t.Assert(array1.Sum(), 21)
t.Assert(array2.Sum(), 18)
})
}
func TestStrArray_PopRand(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"0", "1", "2", "3", "4", "5", "6"}
array1 := garray.NewStrArrayFrom(a1)
str1 := array1.PopRand()
gtest.Assert(strings.Contains("0,1,2,3,4,5,6", str1), true)
gtest.Assert(array1.Len(), 6)
t.Assert(strings.Contains("0,1,2,3,4,5,6", str1), true)
t.Assert(array1.Len(), 6)
})
}
func TestStrArray_Clone(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"0", "1", "2", "3", "4", "5", "6"}
array1 := garray.NewStrArrayFrom(a1)
array2 := array1.Clone()
gtest.Assert(array2, array1)
gtest.Assert(array2.Len(), 7)
t.Assert(array2, array1)
t.Assert(array2.Len(), 7)
})
}
func TestStrArray_CountValues(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"0", "1", "2", "3", "4", "4", "6"}
array1 := garray.NewStrArrayFrom(a1)
m1 := array1.CountValues()
gtest.Assert(len(m1), 6)
gtest.Assert(m1["2"], 1)
gtest.Assert(m1["4"], 2)
t.Assert(len(m1), 6)
t.Assert(m1["2"], 1)
t.Assert(m1["4"], 2)
})
}
func TestStrArray_Remove(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d", "a", "c"}
array1 := garray.NewStrArrayFrom(a1)
s1 := array1.Remove(1)
gtest.Assert(s1, "a")
gtest.Assert(array1.Len(), 4)
t.Assert(s1, "a")
t.Assert(array1.Len(), 4)
s1 = array1.Remove(3)
gtest.Assert(s1, "c")
gtest.Assert(array1.Len(), 3)
t.Assert(s1, "c")
t.Assert(array1.Len(), 3)
})
}
func TestStrArray_RLockFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []string{"a", "b", "c", "d"}
a1 := garray.NewStrArrayFrom(s1, true)
@ -431,25 +441,25 @@ func TestStrArray_RLockFunc(t *testing.T) {
<-ch2 //等待go1完成
// 防止ci抖动,以豪秒为单位
gtest.AssertLT(t2-t1, 20) //go1加的读锁所go2读的时候并没有阻塞。
gtest.Assert(a1.Contains("g"), true)
t.AssertLT(t2-t1, 20) //go1加的读锁所go2读的时候并没有阻塞。
t.Assert(a1.Contains("g"), true)
})
}
func TestStrArray_SortFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []string{"a", "d", "c", "b"}
a1 := garray.NewStrArrayFrom(s1)
func1 := func(v1, v2 string) bool {
return v1 < v2
}
a11 := a1.SortFunc(func1)
gtest.Assert(a11, []string{"a", "b", "c", "d"})
t.Assert(a11, []string{"a", "b", "c", "d"})
})
}
func TestStrArray_LockFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []string{"a", "b", "c", "d"}
a1 := garray.NewStrArrayFrom(s1, true)
@ -475,31 +485,31 @@ func TestStrArray_LockFunc(t *testing.T) {
<-ch2 //等待go1完成
// 防止ci抖动,以豪秒为单位
gtest.AssertGT(t2-t1, 20) //go1加的读写互斥锁所go2读的时候被阻塞。
gtest.Assert(a1.Contains("g"), true)
t.AssertGT(t2-t1, 20) //go1加的读写互斥锁所go2读的时候被阻塞。
t.Assert(a1.Contains("g"), true)
})
}
func TestStrArray_Json(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []string{"a", "b", "d", "c"}
a1 := garray.NewStrArrayFrom(s1)
b1, err1 := json.Marshal(a1)
b2, err2 := json.Marshal(s1)
gtest.Assert(b1, b2)
gtest.Assert(err1, err2)
t.Assert(b1, b2)
t.Assert(err1, err2)
a2 := garray.NewStrArray()
err1 = json.Unmarshal(b2, &a2)
gtest.Assert(a2.Slice(), s1)
t.Assert(a2.Slice(), s1)
var a3 garray.StrArray
err := json.Unmarshal(b2, &a3)
gtest.Assert(err, nil)
gtest.Assert(a3.Slice(), s1)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
type User struct {
Name string
Scores *garray.StrArray
@ -509,111 +519,111 @@ func TestStrArray_Json(t *testing.T) {
"Scores": []string{"A+", "A", "A"},
}
b, err := json.Marshal(data)
gtest.Assert(err, nil)
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
gtest.Assert(err, nil)
gtest.Assert(user.Name, data["Name"])
gtest.Assert(user.Scores, data["Scores"])
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.Assert(user.Scores, data["Scores"])
})
}
func TestStrArray_Iterator(t *testing.T) {
slice := g.SliceStr{"a", "b", "d", "c"}
array := garray.NewStrArrayFrom(slice)
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.Iterator(func(k int, v string) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.IteratorAsc(func(k int, v string) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.IteratorDesc(func(k int, v string) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.Iterator(func(k int, v string) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.IteratorAsc(func(k int, v string) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.IteratorDesc(func(k int, v string) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
}
func TestStrArray_RemoveValue(t *testing.T) {
slice := g.SliceStr{"a", "b", "d", "c"}
array := garray.NewStrArrayFrom(slice)
gtest.Case(t, func() {
gtest.Assert(array.RemoveValue("e"), false)
gtest.Assert(array.RemoveValue("b"), true)
gtest.Assert(array.RemoveValue("a"), true)
gtest.Assert(array.RemoveValue("c"), true)
gtest.Assert(array.RemoveValue("f"), false)
gtest.C(t, func(t *gtest.T) {
t.Assert(array.RemoveValue("e"), false)
t.Assert(array.RemoveValue("b"), true)
t.Assert(array.RemoveValue("a"), true)
t.Assert(array.RemoveValue("c"), true)
t.Assert(array.RemoveValue("f"), false)
})
}
func TestStrArray_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Array *garray.StrArray
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": []byte(`["1","2","3"]`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Array.Slice(), g.SliceStr{"1", "2", "3"})
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Array.Slice(), g.SliceStr{"1", "2", "3"})
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": g.SliceStr{"1", "2", "3"},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Array.Slice(), g.SliceStr{"1", "2", "3"})
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Array.Slice(), g.SliceStr{"1", "2", "3"})
})
}
func TestStrArray_FilterEmpty(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array := garray.NewStrArrayFrom(g.SliceStr{"", "1", "2", "0"})
gtest.Assert(array.FilterEmpty(), g.SliceStr{"1", "2", "0"})
t.Assert(array.FilterEmpty(), g.SliceStr{"1", "2", "0"})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array := garray.NewStrArrayFrom(g.SliceStr{"1", "2"})
gtest.Assert(array.FilterEmpty(), g.SliceStr{"1", "2"})
t.Assert(array.FilterEmpty(), g.SliceStr{"1", "2"})
})
}

View File

@ -22,7 +22,7 @@ import (
)
func TestSortedArray_NewSortedArrayFrom(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "f", "c"}
a2 := []interface{}{"h", "j", "i", "k"}
func1 := func(v1, v2 interface{}) int {
@ -34,16 +34,16 @@ func TestSortedArray_NewSortedArrayFrom(t *testing.T) {
array1 := garray.NewSortedArrayFrom(a1, func1)
array2 := garray.NewSortedArrayFrom(a2, func2)
gtest.Assert(array1.Len(), 3)
gtest.Assert(array1, []interface{}{"a", "c", "f"})
t.Assert(array1.Len(), 3)
t.Assert(array1, []interface{}{"a", "c", "f"})
gtest.Assert(array2.Len(), 4)
gtest.Assert(array2, []interface{}{"k", "i", "j", "h"})
t.Assert(array2.Len(), 4)
t.Assert(array2, []interface{}{"k", "i", "j", "h"})
})
}
func TestNewSortedArrayFromCopy(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "f", "c"}
func1 := func(v1, v2 interface{}) int {
@ -54,15 +54,15 @@ func TestNewSortedArrayFromCopy(t *testing.T) {
}
array1 := garray.NewSortedArrayFromCopy(a1, func1)
array2 := garray.NewSortedArrayFromCopy(a1, func2)
gtest.Assert(array1.Len(), 3)
gtest.Assert(array1, []interface{}{"a", "c", "f"})
gtest.Assert(array1.Len(), 3)
gtest.Assert(array2, []interface{}{"c", "f", "a"})
t.Assert(array1.Len(), 3)
t.Assert(array1, []interface{}{"a", "c", "f"})
t.Assert(array1.Len(), 3)
t.Assert(array2, []interface{}{"c", "f", "a"})
})
}
func TestSortedArray_SetArray(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "f", "c"}
a2 := []interface{}{"e", "h", "g", "k"}
@ -72,171 +72,183 @@ func TestSortedArray_SetArray(t *testing.T) {
array1 := garray.NewSortedArrayFrom(a1, func1)
array1.SetArray(a2)
gtest.Assert(array1.Len(), 4)
gtest.Assert(array1, []interface{}{"e", "g", "h", "k"})
t.Assert(array1.Len(), 4)
t.Assert(array1, []interface{}{"e", "g", "h", "k"})
})
}
func TestSortedArray_Sort(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "f", "c"}
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
}
array1 := garray.NewSortedArrayFrom(a1, func1)
array1.Sort()
gtest.Assert(array1.Len(), 3)
gtest.Assert(array1, []interface{}{"a", "c", "f"})
t.Assert(array1.Len(), 3)
t.Assert(array1, []interface{}{"a", "c", "f"})
})
}
func TestSortedArray_Get(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "f", "c"}
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
}
array1 := garray.NewSortedArrayFrom(a1, func1)
gtest.Assert(array1.Get(2), "f")
gtest.Assert(array1.Get(1), "c")
t.Assert(array1.Get(2), "f")
t.Assert(array1.Get(1), "c")
})
}
func TestSortedArray_Remove(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c", "b"}
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
}
array1 := garray.NewSortedArrayFrom(a1, func1)
i1 := array1.Remove(1)
gtest.Assert(gconv.String(i1), "b")
gtest.Assert(array1.Len(), 3)
gtest.Assert(array1.Contains("b"), false)
t.Assert(gconv.String(i1), "b")
t.Assert(array1.Len(), 3)
t.Assert(array1.Contains("b"), false)
gtest.Assert(array1.Remove(-1), nil)
gtest.Assert(array1.Remove(100000), nil)
t.Assert(array1.Remove(-1), nil)
t.Assert(array1.Remove(100000), nil)
i2 := array1.Remove(0)
gtest.Assert(gconv.String(i2), "a")
gtest.Assert(array1.Len(), 2)
gtest.Assert(array1.Contains("a"), false)
t.Assert(gconv.String(i2), "a")
t.Assert(array1.Len(), 2)
t.Assert(array1.Contains("a"), false)
i3 := array1.Remove(1)
gtest.Assert(gconv.String(i3), "d")
gtest.Assert(array1.Len(), 1)
gtest.Assert(array1.Contains("d"), false)
t.Assert(gconv.String(i3), "d")
t.Assert(array1.Len(), 1)
t.Assert(array1.Contains("d"), false)
})
}
func TestSortedArray_PopLeft(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c", "b"}
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
}
array1 := garray.NewSortedArrayFrom(a1, func1)
i1 := array1.PopLeft()
gtest.Assert(gconv.String(i1), "a")
gtest.Assert(array1.Len(), 3)
gtest.Assert(array1, []interface{}{"b", "c", "d"})
t.Assert(gconv.String(i1), "a")
t.Assert(array1.Len(), 3)
t.Assert(array1, []interface{}{"b", "c", "d"})
})
}
func TestSortedArray_PopRight(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c", "b"}
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
}
array1 := garray.NewSortedArrayFrom(a1, func1)
i1 := array1.PopRight()
gtest.Assert(gconv.String(i1), "d")
gtest.Assert(array1.Len(), 3)
gtest.Assert(array1, []interface{}{"a", "b", "c"})
t.Assert(gconv.String(i1), "d")
t.Assert(array1.Len(), 3)
t.Assert(array1, []interface{}{"a", "b", "c"})
})
}
func TestSortedArray_PopRand(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c", "b"}
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
}
array1 := garray.NewSortedArrayFrom(a1, func1)
i1 := array1.PopRand()
gtest.AssertIN(i1, []interface{}{"a", "d", "c", "b"})
gtest.Assert(array1.Len(), 3)
t.AssertIN(i1, []interface{}{"a", "d", "c", "b"})
t.Assert(array1.Len(), 3)
})
}
func TestSortedArray_PopRands(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c", "b"}
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
}
array1 := garray.NewSortedArrayFrom(a1, func1)
i1 := array1.PopRands(2)
gtest.Assert(len(i1), 2)
gtest.AssertIN(i1, []interface{}{"a", "d", "c", "b"})
gtest.Assert(array1.Len(), 2)
t.Assert(len(i1), 2)
t.AssertIN(i1, []interface{}{"a", "d", "c", "b"})
t.Assert(array1.Len(), 2)
i2 := array1.PopRands(3)
gtest.Assert(len(i1), 2)
gtest.AssertIN(i2, []interface{}{"a", "d", "c", "b"})
gtest.Assert(array1.Len(), 0)
t.Assert(len(i1), 2)
t.AssertIN(i2, []interface{}{"a", "d", "c", "b"})
t.Assert(array1.Len(), 0)
})
}
func TestSortedArray_Empty(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedArray(gutil.ComparatorInt)
t.Assert(array.PopLeft(), nil)
t.Assert(array.PopLefts(10), nil)
t.Assert(array.PopRight(), nil)
t.Assert(array.PopRights(10), nil)
t.Assert(array.PopRand(), nil)
t.Assert(array.PopRands(10), nil)
})
}
func TestSortedArray_PopLefts(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c", "b", "e", "f"}
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
}
array1 := garray.NewSortedArrayFrom(a1, func1)
i1 := array1.PopLefts(2)
gtest.Assert(len(i1), 2)
gtest.AssertIN(i1, []interface{}{"a", "d", "c", "b", "e", "f"})
gtest.Assert(array1.Len(), 4)
t.Assert(len(i1), 2)
t.AssertIN(i1, []interface{}{"a", "d", "c", "b", "e", "f"})
t.Assert(array1.Len(), 4)
i2 := array1.PopLefts(5)
gtest.Assert(len(i2), 4)
gtest.AssertIN(i1, []interface{}{"a", "d", "c", "b", "e", "f"})
gtest.Assert(array1.Len(), 0)
t.Assert(len(i2), 4)
t.AssertIN(i1, []interface{}{"a", "d", "c", "b", "e", "f"})
t.Assert(array1.Len(), 0)
})
}
func TestSortedArray_PopRights(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c", "b", "e", "f"}
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
}
array1 := garray.NewSortedArrayFrom(a1, func1)
i1 := array1.PopRights(2)
gtest.Assert(len(i1), 2)
gtest.Assert(i1, []interface{}{"e", "f"})
gtest.Assert(array1.Len(), 4)
t.Assert(len(i1), 2)
t.Assert(i1, []interface{}{"e", "f"})
t.Assert(array1.Len(), 4)
i2 := array1.PopRights(10)
gtest.Assert(len(i2), 4)
t.Assert(len(i2), 4)
})
}
func TestSortedArray_Range(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c", "b", "e", "f"}
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
@ -244,25 +256,25 @@ func TestSortedArray_Range(t *testing.T) {
array1 := garray.NewSortedArrayFrom(a1, func1)
array2 := garray.NewSortedArrayFrom(a1, func1, true)
i1 := array1.Range(2, 5)
gtest.Assert(i1, []interface{}{"c", "d", "e"})
gtest.Assert(array1.Len(), 6)
t.Assert(i1, []interface{}{"c", "d", "e"})
t.Assert(array1.Len(), 6)
i2 := array1.Range(7, 5)
gtest.Assert(len(i2), 0)
t.Assert(len(i2), 0)
i2 = array1.Range(-1, 2)
gtest.Assert(i2, []interface{}{"a", "b"})
t.Assert(i2, []interface{}{"a", "b"})
i2 = array1.Range(4, 10)
gtest.Assert(len(i2), 2)
gtest.Assert(i2, []interface{}{"e", "f"})
t.Assert(len(i2), 2)
t.Assert(i2, []interface{}{"e", "f"})
gtest.Assert(array2.Range(1, 3), []interface{}{"b", "c"})
t.Assert(array2.Range(1, 3), []interface{}{"b", "c"})
})
}
func TestSortedArray_Sum(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c", "b", "e", "f"}
a2 := []interface{}{"1", "2", "3", "b", "e", "f"}
a3 := []interface{}{"4", "5", "6"}
@ -272,15 +284,15 @@ func TestSortedArray_Sum(t *testing.T) {
array1 := garray.NewSortedArrayFrom(a1, func1)
array2 := garray.NewSortedArrayFrom(a2, func1)
array3 := garray.NewSortedArrayFrom(a3, func1)
gtest.Assert(array1.Sum(), 0)
gtest.Assert(array2.Sum(), 6)
gtest.Assert(array3.Sum(), 15)
t.Assert(array1.Sum(), 0)
t.Assert(array2.Sum(), 6)
t.Assert(array3.Sum(), 15)
})
}
func TestSortedArray_Clone(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c", "b", "e", "f"}
func1 := func(v1, v2 interface{}) int {
@ -288,30 +300,30 @@ func TestSortedArray_Clone(t *testing.T) {
}
array1 := garray.NewSortedArrayFrom(a1, func1)
array2 := array1.Clone()
gtest.Assert(array1, array2)
t.Assert(array1, array2)
array1.Remove(1)
gtest.AssertNE(array1, array2)
t.AssertNE(array1, array2)
})
}
func TestSortedArray_Clear(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c", "b", "e", "f"}
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
}
array1 := garray.NewSortedArrayFrom(a1, func1)
gtest.Assert(array1.Len(), 6)
t.Assert(array1.Len(), 6)
array1.Clear()
gtest.Assert(array1.Len(), 0)
t.Assert(array1.Len(), 0)
})
}
func TestSortedArray_Chunk(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c", "b", "e"}
func1 := func(v1, v2 interface{}) int {
@ -319,45 +331,45 @@ func TestSortedArray_Chunk(t *testing.T) {
}
array1 := garray.NewSortedArrayFrom(a1, func1)
i1 := array1.Chunk(2)
gtest.Assert(len(i1), 3)
gtest.Assert(i1[0], []interface{}{"a", "b"})
gtest.Assert(i1[2], []interface{}{"e"})
t.Assert(len(i1), 3)
t.Assert(i1[0], []interface{}{"a", "b"})
t.Assert(i1[2], []interface{}{"e"})
i1 = array1.Chunk(0)
gtest.Assert(len(i1), 0)
t.Assert(len(i1), 0)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{1, 2, 3, 4, 5}
array1 := garray.NewSortedArrayFrom(a1, gutil.ComparatorInt)
chunks := array1.Chunk(3)
gtest.Assert(len(chunks), 2)
gtest.Assert(chunks[0], []interface{}{1, 2, 3})
gtest.Assert(chunks[1], []interface{}{4, 5})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 2)
t.Assert(chunks[0], []interface{}{1, 2, 3})
t.Assert(chunks[1], []interface{}{4, 5})
t.Assert(array1.Chunk(0), nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{1, 2, 3, 4, 5, 6}
array1 := garray.NewSortedArrayFrom(a1, gutil.ComparatorInt)
chunks := array1.Chunk(2)
gtest.Assert(len(chunks), 3)
gtest.Assert(chunks[0], []interface{}{1, 2})
gtest.Assert(chunks[1], []interface{}{3, 4})
gtest.Assert(chunks[2], []interface{}{5, 6})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 3)
t.Assert(chunks[0], []interface{}{1, 2})
t.Assert(chunks[1], []interface{}{3, 4})
t.Assert(chunks[2], []interface{}{5, 6})
t.Assert(array1.Chunk(0), nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{1, 2, 3, 4, 5, 6}
array1 := garray.NewSortedArrayFrom(a1, gutil.ComparatorInt)
chunks := array1.Chunk(3)
gtest.Assert(len(chunks), 2)
gtest.Assert(chunks[0], []interface{}{1, 2, 3})
gtest.Assert(chunks[1], []interface{}{4, 5, 6})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 2)
t.Assert(chunks[0], []interface{}{1, 2, 3})
t.Assert(chunks[1], []interface{}{4, 5, 6})
t.Assert(array1.Chunk(0), nil)
})
}
func TestSortedArray_SubSlice(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c", "b", "e"}
func1 := func(v1, v2 interface{}) int {
@ -366,28 +378,28 @@ func TestSortedArray_SubSlice(t *testing.T) {
array1 := garray.NewSortedArrayFrom(a1, func1)
array2 := garray.NewSortedArrayFrom(a1, func1, true)
i1 := array1.SubSlice(2, 3)
gtest.Assert(len(i1), 3)
gtest.Assert(i1, []interface{}{"c", "d", "e"})
t.Assert(len(i1), 3)
t.Assert(i1, []interface{}{"c", "d", "e"})
i1 = array1.SubSlice(2, 6)
gtest.Assert(len(i1), 3)
gtest.Assert(i1, []interface{}{"c", "d", "e"})
t.Assert(len(i1), 3)
t.Assert(i1, []interface{}{"c", "d", "e"})
i1 = array1.SubSlice(7, 2)
gtest.Assert(len(i1), 0)
t.Assert(len(i1), 0)
s1 := array1.SubSlice(1, -2)
gtest.Assert(s1, nil)
t.Assert(s1, nil)
s1 = array1.SubSlice(-9, 2)
gtest.Assert(s1, nil)
gtest.Assert(array2.SubSlice(1, 3), []interface{}{"b", "c", "d"})
t.Assert(s1, nil)
t.Assert(array2.SubSlice(1, 3), []interface{}{"b", "c", "d"})
})
}
func TestSortedArray_Rand(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c"}
func1 := func(v1, v2 interface{}) int {
@ -395,13 +407,13 @@ func TestSortedArray_Rand(t *testing.T) {
}
array1 := garray.NewSortedArrayFrom(a1, func1)
i1 := array1.Rand()
gtest.AssertIN(i1, []interface{}{"a", "d", "c"})
gtest.Assert(array1.Len(), 3)
t.AssertIN(i1, []interface{}{"a", "d", "c"})
t.Assert(array1.Len(), 3)
})
}
func TestSortedArray_Rands(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c"}
func1 := func(v1, v2 interface{}) int {
@ -409,43 +421,43 @@ func TestSortedArray_Rands(t *testing.T) {
}
array1 := garray.NewSortedArrayFrom(a1, func1)
i1 := array1.Rands(2)
gtest.AssertIN(i1, []interface{}{"a", "d", "c"})
gtest.Assert(len(i1), 2)
gtest.Assert(array1.Len(), 3)
t.AssertIN(i1, []interface{}{"a", "d", "c"})
t.Assert(len(i1), 2)
t.Assert(array1.Len(), 3)
i1 = array1.Rands(4)
gtest.Assert(len(i1), 3)
t.Assert(len(i1), 3)
})
}
func TestSortedArray_Join(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c"}
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
}
array1 := garray.NewSortedArrayFrom(a1, func1)
gtest.Assert(array1.Join(","), `a,c,d`)
gtest.Assert(array1.Join("."), `a.c.d`)
t.Assert(array1.Join(","), `a,c,d`)
t.Assert(array1.Join("."), `a.c.d`)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{0, 1, `"a"`, `\a`}
array1 := garray.NewSortedArrayFrom(a1, gutil.ComparatorString)
gtest.Assert(array1.Join("."), `"a".0.1.\a`)
t.Assert(array1.Join("."), `"a".0.1.\a`)
})
}
func TestSortedArray_String(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{0, 1, "a", "b"}
array1 := garray.NewSortedArrayFrom(a1, gutil.ComparatorString)
gtest.Assert(array1.String(), `[0,1,"a","b"]`)
t.Assert(array1.String(), `[0,1,"a","b"]`)
})
}
func TestSortedArray_CountValues(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c", "c"}
func1 := func(v1, v2 interface{}) int {
@ -453,15 +465,15 @@ func TestSortedArray_CountValues(t *testing.T) {
}
array1 := garray.NewSortedArrayFrom(a1, func1)
m1 := array1.CountValues()
gtest.Assert(len(m1), 3)
gtest.Assert(m1["c"], 2)
gtest.Assert(m1["a"], 1)
t.Assert(len(m1), 3)
t.Assert(m1["c"], 2)
t.Assert(m1["a"], 1)
})
}
func TestSortedArray_SetUnique(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []interface{}{"a", "d", "c", "c"}
func1 := func(v1, v2 interface{}) int {
@ -469,13 +481,13 @@ func TestSortedArray_SetUnique(t *testing.T) {
}
array1 := garray.NewSortedArrayFrom(a1, func1)
array1.SetUnique(true)
gtest.Assert(array1.Len(), 3)
gtest.Assert(array1, []interface{}{"a", "c", "d"})
t.Assert(array1.Len(), 3)
t.Assert(array1, []interface{}{"a", "c", "d"})
})
}
func TestSortedArray_LockFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
}
@ -504,13 +516,13 @@ func TestSortedArray_LockFunc(t *testing.T) {
<-ch2 //等待go1完成
// 防止ci抖动,以豪秒为单位
gtest.AssertGT(t2-t1, 20) //go1加的读写互斥锁所go2读的时候被阻塞。
gtest.Assert(a1.Contains("g"), true)
t.AssertGT(t2-t1, 20) //go1加的读写互斥锁所go2读的时候被阻塞。
t.Assert(a1.Contains("g"), true)
})
}
func TestSortedArray_RLockFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
func1 := func(v1, v2 interface{}) int {
return strings.Compare(gconv.String(v1), gconv.String(v2))
}
@ -539,13 +551,13 @@ func TestSortedArray_RLockFunc(t *testing.T) {
<-ch2 //等待go1完成
// 防止ci抖动,以豪秒为单位
gtest.AssertLT(t2-t1, 20) //go1加的读锁所go2读的时候不会被阻塞。
gtest.Assert(a1.Contains("g"), true)
t.AssertLT(t2-t1, 20) //go1加的读锁所go2读的时候不会被阻塞。
t.Assert(a1.Contains("g"), true)
})
}
func TestSortedArray_Merge(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
func1 := func(v1, v2 interface{}) int {
if gconv.Int(v1) < gconv.Int(v2) {
return 0
@ -564,38 +576,38 @@ func TestSortedArray_Merge(t *testing.T) {
a1 := garray.NewSortedArrayFrom(s1, func1)
gtest.Assert(a1.Merge(s2).Len(), 6)
gtest.Assert(a1.Merge(i1).Len(), 9)
gtest.Assert(a1.Merge(i2).Len(), 10)
gtest.Assert(a1.Merge(s3).Len(), 12)
gtest.Assert(a1.Merge(s4).Len(), 14)
gtest.Assert(a1.Merge(s5).Len(), 16)
gtest.Assert(a1.Merge(s6).Len(), 19)
t.Assert(a1.Merge(s2).Len(), 6)
t.Assert(a1.Merge(i1).Len(), 9)
t.Assert(a1.Merge(i2).Len(), 10)
t.Assert(a1.Merge(s3).Len(), 12)
t.Assert(a1.Merge(s4).Len(), 14)
t.Assert(a1.Merge(s5).Len(), 16)
t.Assert(a1.Merge(s6).Len(), 19)
})
}
func TestSortedArray_Json(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []interface{}{"a", "b", "d", "c"}
s2 := []interface{}{"a", "b", "c", "d"}
a1 := garray.NewSortedArrayFrom(s1, gutil.ComparatorString)
b1, err1 := json.Marshal(a1)
b2, err2 := json.Marshal(s1)
gtest.Assert(b1, b2)
gtest.Assert(err1, err2)
t.Assert(b1, b2)
t.Assert(err1, err2)
a2 := garray.NewSortedArray(gutil.ComparatorString)
err1 = json.Unmarshal(b2, &a2)
gtest.Assert(a2.Slice(), s2)
t.Assert(a2.Slice(), s2)
var a3 garray.SortedArray
err := json.Unmarshal(b2, &a3)
gtest.Assert(err, nil)
gtest.Assert(a3.Slice(), s1)
gtest.Assert(a3.Interfaces(), s1)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
t.Assert(a3.Interfaces(), s1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
type User struct {
Name string
Scores *garray.SortedArray
@ -605,127 +617,127 @@ func TestSortedArray_Json(t *testing.T) {
"Scores": []int{99, 100, 98},
}
b, err := json.Marshal(data)
gtest.Assert(err, nil)
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
gtest.Assert(err, nil)
gtest.Assert(user.Name, data["Name"])
gtest.AssertNE(user.Scores, nil)
gtest.Assert(user.Scores.Len(), 3)
gtest.AssertIN(user.Scores.PopLeft(), data["Scores"])
gtest.AssertIN(user.Scores.PopLeft(), data["Scores"])
gtest.AssertIN(user.Scores.PopLeft(), data["Scores"])
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.AssertNE(user.Scores, nil)
t.Assert(user.Scores.Len(), 3)
t.AssertIN(user.Scores.PopLeft(), data["Scores"])
t.AssertIN(user.Scores.PopLeft(), data["Scores"])
t.AssertIN(user.Scores.PopLeft(), data["Scores"])
})
}
func TestSortedArray_Iterator(t *testing.T) {
slice := g.Slice{"a", "b", "d", "c"}
array := garray.NewSortedArrayFrom(slice, gutil.ComparatorString)
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.Iterator(func(k int, v interface{}) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.IteratorAsc(func(k int, v interface{}) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.IteratorDesc(func(k int, v interface{}) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.Iterator(func(k int, v interface{}) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.IteratorAsc(func(k int, v interface{}) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.IteratorDesc(func(k int, v interface{}) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
}
func TestSortedArray_RemoveValue(t *testing.T) {
slice := g.Slice{"a", "b", "d", "c"}
array := garray.NewSortedArrayFrom(slice, gutil.ComparatorString)
gtest.Case(t, func() {
gtest.Assert(array.RemoveValue("e"), false)
gtest.Assert(array.RemoveValue("b"), true)
gtest.Assert(array.RemoveValue("a"), true)
gtest.Assert(array.RemoveValue("c"), true)
gtest.Assert(array.RemoveValue("f"), false)
gtest.C(t, func(t *gtest.T) {
t.Assert(array.RemoveValue("e"), false)
t.Assert(array.RemoveValue("b"), true)
t.Assert(array.RemoveValue("a"), true)
t.Assert(array.RemoveValue("c"), true)
t.Assert(array.RemoveValue("f"), false)
})
}
func TestSortedArray_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Array *garray.SortedArray
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": []byte(`[2,3,1]`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3})
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Array.Slice(), g.Slice{1, 2, 3})
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": g.Slice{2, 3, 1},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3})
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Array.Slice(), g.Slice{1, 2, 3})
})
}
func TestSortedArray_FilterNil(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
values := g.Slice{0, 1, 2, 3, 4, "", g.Slice{}}
array := garray.NewSortedArrayFromCopy(values, gutil.ComparatorInt)
gtest.Assert(array.FilterNil().Slice(), g.Slice{0, "", g.Slice{}, 1, 2, 3, 4})
t.Assert(array.FilterNil().Slice(), g.Slice{0, "", g.Slice{}, 1, 2, 3, 4})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedArrayFromCopy(g.Slice{nil, 1, 2, 3, 4, nil}, gutil.ComparatorInt)
gtest.Assert(array.FilterNil(), g.Slice{1, 2, 3, 4})
t.Assert(array.FilterNil(), g.Slice{1, 2, 3, 4})
})
}
func TestSortedArray_FilterEmpty(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedArrayFrom(g.Slice{0, 1, 2, 3, 4, "", g.Slice{}}, gutil.ComparatorInt)
gtest.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4})
t.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedArrayFrom(g.Slice{1, 2, 3, 4}, gutil.ComparatorInt)
gtest.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4})
t.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4})
})
}

View File

@ -21,355 +21,367 @@ import (
)
func TestNewSortedIntArrayFrom(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 3, 2, 1, 4, 5, 6}
array1 := garray.NewSortedIntArrayFrom(a1, true)
gtest.Assert(array1.Join("."), "0.1.2.3.4.5.6")
gtest.Assert(array1.Slice(), a1)
gtest.Assert(array1.Interfaces(), a1)
t.Assert(array1.Join("."), "0.1.2.3.4.5.6")
t.Assert(array1.Slice(), a1)
t.Assert(array1.Interfaces(), a1)
})
}
func TestNewSortedIntArrayFromCopy(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 5, 2, 1, 4, 3, 6}
array1 := garray.NewSortedIntArrayFromCopy(a1, false)
gtest.Assert(array1.Join("."), "0.1.2.3.4.5.6")
t.Assert(array1.Join("."), "0.1.2.3.4.5.6")
})
}
func TestSortedIntArray_SetArray(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 1, 2, 3}
a2 := []int{4, 5, 6}
array1 := garray.NewSortedIntArrayFrom(a1)
array2 := array1.SetArray(a2)
gtest.Assert(array2.Len(), 3)
gtest.Assert(array2.Search(3), -1)
gtest.Assert(array2.Search(5), 1)
gtest.Assert(array2.Search(6), 2)
t.Assert(array2.Len(), 3)
t.Assert(array2.Search(3), -1)
t.Assert(array2.Search(5), 1)
t.Assert(array2.Search(6), 2)
})
}
func TestSortedIntArray_Sort(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{0, 3, 2, 1}
array1 := garray.NewSortedIntArrayFrom(a1)
array2 := array1.Sort()
gtest.Assert(array2.Len(), 4)
gtest.Assert(array2, []int{0, 1, 2, 3})
t.Assert(array2.Len(), 4)
t.Assert(array2, []int{0, 1, 2, 3})
})
}
func TestSortedIntArray_Get(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 3, 5, 0}
array1 := garray.NewSortedIntArrayFrom(a1)
gtest.Assert(array1.Get(0), 0)
gtest.Assert(array1.Get(1), 1)
gtest.Assert(array1.Get(3), 5)
t.Assert(array1.Get(0), 0)
t.Assert(array1.Get(1), 1)
t.Assert(array1.Get(3), 5)
})
}
func TestSortedIntArray_Remove(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 3, 5, 0}
array1 := garray.NewSortedIntArrayFrom(a1)
gtest.Assert(array1.Remove(-1), 0)
gtest.Assert(array1.Remove(100000), 0)
t.Assert(array1.Remove(-1), 0)
t.Assert(array1.Remove(100000), 0)
i1 := array1.Remove(2)
gtest.Assert(i1, 3)
gtest.Assert(array1.Search(5), 2)
t.Assert(i1, 3)
t.Assert(array1.Search(5), 2)
// 再次删除剩下的数组中的第一个
i2 := array1.Remove(0)
gtest.Assert(i2, 0)
gtest.Assert(array1.Search(5), 1)
t.Assert(i2, 0)
t.Assert(array1.Search(5), 1)
a2 := []int{1, 3, 4}
array2 := garray.NewSortedIntArrayFrom(a2)
i3 := array2.Remove(1)
gtest.Assert(array2.Search(1), 0)
gtest.Assert(i3, 3)
t.Assert(array2.Search(1), 0)
t.Assert(i3, 3)
i3 = array2.Remove(1)
gtest.Assert(array2.Search(4), -1)
gtest.Assert(i3, 4)
t.Assert(array2.Search(4), -1)
t.Assert(i3, 4)
})
}
func TestSortedIntArray_PopLeft(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 3, 5, 2}
array1 := garray.NewSortedIntArrayFrom(a1)
i1 := array1.PopLeft()
gtest.Assert(i1, 1)
gtest.Assert(array1.Len(), 3)
gtest.Assert(array1.Search(1), -1)
t.Assert(i1, 1)
t.Assert(array1.Len(), 3)
t.Assert(array1.Search(1), -1)
})
}
func TestSortedIntArray_PopRight(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 3, 5, 2}
array1 := garray.NewSortedIntArrayFrom(a1)
i1 := array1.PopRight()
gtest.Assert(i1, 5)
gtest.Assert(array1.Len(), 3)
gtest.Assert(array1.Search(5), -1)
t.Assert(i1, 5)
t.Assert(array1.Len(), 3)
t.Assert(array1.Search(5), -1)
})
}
func TestSortedIntArray_PopRand(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 3, 5, 2}
array1 := garray.NewSortedIntArrayFrom(a1)
i1 := array1.PopRand()
gtest.Assert(array1.Len(), 3)
gtest.Assert(array1.Search(i1), -1)
gtest.AssertIN(i1, []int{1, 3, 5, 2})
t.Assert(array1.Len(), 3)
t.Assert(array1.Search(i1), -1)
t.AssertIN(i1, []int{1, 3, 5, 2})
})
}
func TestSortedIntArray_PopRands(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 3, 5, 2}
array1 := garray.NewSortedIntArrayFrom(a1)
ns1 := array1.PopRands(2)
gtest.Assert(array1.Len(), 2)
gtest.AssertIN(ns1, []int{1, 3, 5, 2})
t.Assert(array1.Len(), 2)
t.AssertIN(ns1, []int{1, 3, 5, 2})
a2 := []int{1, 3, 5, 2}
array2 := garray.NewSortedIntArrayFrom(a2)
ns2 := array2.PopRands(5)
gtest.Assert(array2.Len(), 0)
gtest.Assert(len(ns2), 4)
gtest.AssertIN(ns2, []int{1, 3, 5, 2})
t.Assert(array2.Len(), 0)
t.Assert(len(ns2), 4)
t.AssertIN(ns2, []int{1, 3, 5, 2})
})
}
func TestSortedIntArray_Empty(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedIntArray()
t.Assert(array.PopLeft(), 0)
t.Assert(array.PopLefts(10), nil)
t.Assert(array.PopRight(), 0)
t.Assert(array.PopRights(10), nil)
t.Assert(array.PopRand(), 0)
t.Assert(array.PopRands(10), nil)
})
}
func TestSortedIntArray_PopLefts(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 3, 5, 2}
array1 := garray.NewSortedIntArrayFrom(a1)
ns1 := array1.PopLefts(2)
gtest.Assert(array1.Len(), 2)
gtest.Assert(ns1, []int{1, 2})
t.Assert(array1.Len(), 2)
t.Assert(ns1, []int{1, 2})
a2 := []int{1, 3, 5, 2}
array2 := garray.NewSortedIntArrayFrom(a2)
ns2 := array2.PopLefts(5)
gtest.Assert(array2.Len(), 0)
gtest.AssertIN(ns2, []int{1, 3, 5, 2})
t.Assert(array2.Len(), 0)
t.AssertIN(ns2, []int{1, 3, 5, 2})
})
}
func TestSortedIntArray_PopRights(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 3, 5, 2}
array1 := garray.NewSortedIntArrayFrom(a1)
ns1 := array1.PopRights(2)
gtest.Assert(array1.Len(), 2)
gtest.Assert(ns1, []int{3, 5})
t.Assert(array1.Len(), 2)
t.Assert(ns1, []int{3, 5})
a2 := []int{1, 3, 5, 2}
array2 := garray.NewSortedIntArrayFrom(a2)
ns2 := array2.PopRights(5)
gtest.Assert(array2.Len(), 0)
gtest.AssertIN(ns2, []int{1, 3, 5, 2})
t.Assert(array2.Len(), 0)
t.AssertIN(ns2, []int{1, 3, 5, 2})
})
}
func TestSortedIntArray_Range(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 3, 5, 2, 6, 7}
array1 := garray.NewSortedIntArrayFrom(a1)
array2 := garray.NewSortedIntArrayFrom(a1, true)
ns1 := array1.Range(1, 4)
gtest.Assert(len(ns1), 3)
gtest.Assert(ns1, []int{2, 3, 5})
t.Assert(len(ns1), 3)
t.Assert(ns1, []int{2, 3, 5})
ns2 := array1.Range(5, 4)
gtest.Assert(len(ns2), 0)
t.Assert(len(ns2), 0)
ns3 := array1.Range(-1, 4)
gtest.Assert(len(ns3), 4)
t.Assert(len(ns3), 4)
nsl := array1.Range(5, 8)
gtest.Assert(len(nsl), 1)
gtest.Assert(array2.Range(1, 2), []int{2})
t.Assert(len(nsl), 1)
t.Assert(array2.Range(1, 2), []int{2})
})
}
func TestSortedIntArray_Sum(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 3, 5}
array1 := garray.NewSortedIntArrayFrom(a1)
n1 := array1.Sum()
gtest.Assert(n1, 9)
t.Assert(n1, 9)
})
}
func TestSortedIntArray_Join(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 3, 5}
array1 := garray.NewSortedIntArrayFrom(a1)
gtest.Assert(array1.Join("."), `1.3.5`)
t.Assert(array1.Join("."), `1.3.5`)
})
}
func TestSortedIntArray_String(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 3, 5}
array1 := garray.NewSortedIntArrayFrom(a1)
gtest.Assert(array1.String(), `[1,3,5]`)
t.Assert(array1.String(), `[1,3,5]`)
})
}
func TestSortedIntArray_Contains(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 3, 5}
array1 := garray.NewSortedIntArrayFrom(a1)
gtest.Assert(array1.Contains(4), false)
t.Assert(array1.Contains(4), false)
})
}
func TestSortedIntArray_Clone(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 3, 5}
array1 := garray.NewSortedIntArrayFrom(a1)
array2 := array1.Clone()
gtest.Assert(array2.Len(), 3)
gtest.Assert(array2, array1)
t.Assert(array2.Len(), 3)
t.Assert(array2, array1)
})
}
func TestSortedIntArray_Clear(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 3, 5}
array1 := garray.NewSortedIntArrayFrom(a1)
array1.Clear()
gtest.Assert(array1.Len(), 0)
t.Assert(array1.Len(), 0)
})
}
func TestSortedIntArray_Chunk(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5}
array1 := garray.NewSortedIntArrayFrom(a1)
ns1 := array1.Chunk(2) //按每几个元素切成一个数组
ns2 := array1.Chunk(-1)
gtest.Assert(len(ns1), 3)
gtest.Assert(ns1[0], []int{1, 2})
gtest.Assert(ns1[2], []int{5})
gtest.Assert(len(ns2), 0)
t.Assert(len(ns1), 3)
t.Assert(ns1[0], []int{1, 2})
t.Assert(ns1[2], []int{5})
t.Assert(len(ns2), 0)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5}
array1 := garray.NewSortedIntArrayFrom(a1)
chunks := array1.Chunk(3)
gtest.Assert(len(chunks), 2)
gtest.Assert(chunks[0], []int{1, 2, 3})
gtest.Assert(chunks[1], []int{4, 5})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 2)
t.Assert(chunks[0], []int{1, 2, 3})
t.Assert(chunks[1], []int{4, 5})
t.Assert(array1.Chunk(0), nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5, 6}
array1 := garray.NewSortedIntArrayFrom(a1)
chunks := array1.Chunk(2)
gtest.Assert(len(chunks), 3)
gtest.Assert(chunks[0], []int{1, 2})
gtest.Assert(chunks[1], []int{3, 4})
gtest.Assert(chunks[2], []int{5, 6})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 3)
t.Assert(chunks[0], []int{1, 2})
t.Assert(chunks[1], []int{3, 4})
t.Assert(chunks[2], []int{5, 6})
t.Assert(array1.Chunk(0), nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5, 6}
array1 := garray.NewSortedIntArrayFrom(a1)
chunks := array1.Chunk(3)
gtest.Assert(len(chunks), 2)
gtest.Assert(chunks[0], []int{1, 2, 3})
gtest.Assert(chunks[1], []int{4, 5, 6})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 2)
t.Assert(chunks[0], []int{1, 2, 3})
t.Assert(chunks[1], []int{4, 5, 6})
t.Assert(array1.Chunk(0), nil)
})
}
func TestSortedIntArray_SubSlice(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5}
array1 := garray.NewSortedIntArrayFrom(a1)
array2 := garray.NewSortedIntArrayFrom(a1, true)
ns1 := array1.SubSlice(1, 2)
gtest.Assert(len(ns1), 2)
gtest.Assert(ns1, []int{2, 3})
t.Assert(len(ns1), 2)
t.Assert(ns1, []int{2, 3})
ns2 := array1.SubSlice(7, 2)
gtest.Assert(len(ns2), 0)
t.Assert(len(ns2), 0)
ns3 := array1.SubSlice(3, 5)
gtest.Assert(len(ns3), 2)
gtest.Assert(ns3, []int{4, 5})
t.Assert(len(ns3), 2)
t.Assert(ns3, []int{4, 5})
ns4 := array1.SubSlice(3, 1)
gtest.Assert(len(ns4), 1)
gtest.Assert(ns4, []int{4})
gtest.Assert(array1.SubSlice(-1, 1), []int{5})
gtest.Assert(array1.SubSlice(-9, 1), nil)
gtest.Assert(array1.SubSlice(1, -9), nil)
gtest.Assert(array2.SubSlice(1, 2), []int{2, 3})
t.Assert(len(ns4), 1)
t.Assert(ns4, []int{4})
t.Assert(array1.SubSlice(-1, 1), []int{5})
t.Assert(array1.SubSlice(-9, 1), nil)
t.Assert(array1.SubSlice(1, -9), nil)
t.Assert(array2.SubSlice(1, 2), []int{2, 3})
})
}
func TestSortedIntArray_Rand(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5}
array1 := garray.NewSortedIntArrayFrom(a1)
ns1 := array1.Rand() //按每几个元素切成一个数组
gtest.AssertIN(ns1, a1)
t.AssertIN(ns1, a1)
})
}
func TestSortedIntArray_Rands(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5}
array1 := garray.NewSortedIntArrayFrom(a1)
ns1 := array1.Rands(2) //按每几个元素切成一个数组
gtest.AssertIN(ns1, a1)
gtest.Assert(len(ns1), 2)
t.AssertIN(ns1, a1)
t.Assert(len(ns1), 2)
ns2 := array1.Rands(6) //按每几个元素切成一个数组
gtest.AssertIN(ns2, a1)
gtest.Assert(len(ns2), 5)
t.AssertIN(ns2, a1)
t.Assert(len(ns2), 5)
})
}
func TestSortedIntArray_CountValues(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5, 3}
array1 := garray.NewSortedIntArrayFrom(a1)
ns1 := array1.CountValues() //按每几个元素切成一个数组
gtest.Assert(len(ns1), 5)
gtest.Assert(ns1[2], 1)
gtest.Assert(ns1[3], 2)
t.Assert(len(ns1), 5)
t.Assert(ns1[2], 1)
t.Assert(ns1[3], 2)
})
}
func TestSortedIntArray_SetUnique(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5, 3}
array1 := garray.NewSortedIntArrayFrom(a1)
array1.SetUnique(true)
gtest.Assert(array1.Len(), 5)
gtest.Assert(array1, []int{1, 2, 3, 4, 5})
t.Assert(array1.Len(), 5)
t.Assert(array1, []int{1, 2, 3, 4, 5})
})
}
func TestSortedIntArray_LockFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []int{1, 2, 3, 4}
a1 := garray.NewSortedIntArrayFrom(s1, true)
ch1 := make(chan int64, 3)
@ -394,13 +406,13 @@ func TestSortedIntArray_LockFunc(t *testing.T) {
<-ch2 //等待go1完成
// 防止ci抖动,以豪秒为单位
gtest.AssertGT(t2-t1, 20) //go1加的读写互斥锁所go2读的时候被阻塞。
gtest.Assert(a1.Contains(6), true)
t.AssertGT(t2-t1, 20) //go1加的读写互斥锁所go2读的时候被阻塞。
t.Assert(a1.Contains(6), true)
})
}
func TestSortedIntArray_RLockFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []int{1, 2, 3, 4}
a1 := garray.NewSortedIntArrayFrom(s1, true)
@ -426,13 +438,13 @@ func TestSortedIntArray_RLockFunc(t *testing.T) {
<-ch2 //等待go1完成
// 防止ci抖动,以豪秒为单位
gtest.AssertLT(t2-t1, 20) //go1加的读锁所go2读的时候并没有阻塞。
gtest.Assert(a1.Contains(6), true)
t.AssertLT(t2-t1, 20) //go1加的读锁所go2读的时候并没有阻塞。
t.Assert(a1.Contains(6), true)
})
}
func TestSortedIntArray_Merge(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
func1 := func(v1, v2 interface{}) int {
if gconv.Int(v1) < gconv.Int(v2) {
return 0
@ -449,37 +461,37 @@ func TestSortedIntArray_Merge(t *testing.T) {
s6 := garray.NewSortedIntArrayFrom([]int{1, 2, 3})
a1 := garray.NewSortedIntArrayFrom(i0)
gtest.Assert(a1.Merge(s2).Len(), 6)
gtest.Assert(a1.Merge(i1).Len(), 9)
gtest.Assert(a1.Merge(i2).Len(), 10)
gtest.Assert(a1.Merge(s3).Len(), 12)
gtest.Assert(a1.Merge(s4).Len(), 14)
gtest.Assert(a1.Merge(s5).Len(), 16)
gtest.Assert(a1.Merge(s6).Len(), 19)
t.Assert(a1.Merge(s2).Len(), 6)
t.Assert(a1.Merge(i1).Len(), 9)
t.Assert(a1.Merge(i2).Len(), 10)
t.Assert(a1.Merge(s3).Len(), 12)
t.Assert(a1.Merge(s4).Len(), 14)
t.Assert(a1.Merge(s5).Len(), 16)
t.Assert(a1.Merge(s6).Len(), 19)
})
}
func TestSortedIntArray_Json(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []int{1, 4, 3, 2}
s2 := []int{1, 2, 3, 4}
a1 := garray.NewSortedIntArrayFrom(s1)
b1, err1 := json.Marshal(a1)
b2, err2 := json.Marshal(s1)
gtest.Assert(b1, b2)
gtest.Assert(err1, err2)
t.Assert(b1, b2)
t.Assert(err1, err2)
a2 := garray.NewSortedIntArray()
err1 = json.Unmarshal(b2, &a2)
gtest.Assert(a2.Slice(), s2)
t.Assert(a2.Slice(), s2)
var a3 garray.SortedIntArray
err := json.Unmarshal(b2, &a3)
gtest.Assert(err, nil)
gtest.Assert(a3.Slice(), s1)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
type User struct {
Name string
Scores *garray.SortedIntArray
@ -489,112 +501,112 @@ func TestSortedIntArray_Json(t *testing.T) {
"Scores": []int{99, 100, 98},
}
b, err := json.Marshal(data)
gtest.Assert(err, nil)
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
gtest.Assert(err, nil)
gtest.Assert(user.Name, data["Name"])
gtest.Assert(user.Scores, []int{98, 99, 100})
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.Assert(user.Scores, []int{98, 99, 100})
})
}
func TestSortedIntArray_Iterator(t *testing.T) {
slice := g.SliceInt{10, 20, 30, 40}
array := garray.NewSortedIntArrayFrom(slice)
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.Iterator(func(k int, v int) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.IteratorAsc(func(k int, v int) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.IteratorDesc(func(k int, v int) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.Iterator(func(k int, v int) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.IteratorAsc(func(k int, v int) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.IteratorDesc(func(k int, v int) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
}
func TestSortedIntArray_RemoveValue(t *testing.T) {
slice := g.SliceInt{10, 20, 30, 40}
array := garray.NewSortedIntArrayFrom(slice)
gtest.Case(t, func() {
gtest.Assert(array.RemoveValue(99), false)
gtest.Assert(array.RemoveValue(20), true)
gtest.Assert(array.RemoveValue(10), true)
gtest.Assert(array.RemoveValue(20), false)
gtest.Assert(array.RemoveValue(88), false)
gtest.Assert(array.Len(), 2)
gtest.C(t, func(t *gtest.T) {
t.Assert(array.RemoveValue(99), false)
t.Assert(array.RemoveValue(20), true)
t.Assert(array.RemoveValue(10), true)
t.Assert(array.RemoveValue(20), false)
t.Assert(array.RemoveValue(88), false)
t.Assert(array.Len(), 2)
})
}
func TestSortedIntArray_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Array *garray.SortedIntArray
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": []byte(`[2,3,1]`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3})
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Array.Slice(), g.Slice{1, 2, 3})
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": g.Slice{2, 3, 1},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Array.Slice(), g.Slice{1, 2, 3})
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Array.Slice(), g.Slice{1, 2, 3})
})
}
func TestSortedIntArray_FilterEmpty(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedIntArrayFrom(g.SliceInt{0, 1, 2, 3, 4, 0})
gtest.Assert(array.FilterEmpty(), g.SliceInt{1, 2, 3, 4})
t.Assert(array.FilterEmpty(), g.SliceInt{1, 2, 3, 4})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedIntArrayFrom(g.SliceInt{1, 2, 3, 4})
gtest.Assert(array.FilterEmpty(), g.SliceInt{1, 2, 3, 4})
t.Assert(array.FilterEmpty(), g.SliceInt{1, 2, 3, 4})
})
}

View File

@ -20,362 +20,374 @@ import (
)
func TestNewSortedStrArrayFrom(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"a", "d", "c", "b"}
s1 := garray.NewSortedStrArrayFrom(a1, true)
gtest.Assert(s1, []string{"a", "b", "c", "d"})
t.Assert(s1, []string{"a", "b", "c", "d"})
s2 := garray.NewSortedStrArrayFrom(a1, false)
gtest.Assert(s2, []string{"a", "b", "c", "d"})
t.Assert(s2, []string{"a", "b", "c", "d"})
})
}
func TestNewSortedStrArrayFromCopy(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"a", "d", "c", "b"}
s1 := garray.NewSortedStrArrayFromCopy(a1, true)
gtest.Assert(s1.Len(), 4)
gtest.Assert(s1, []string{"a", "b", "c", "d"})
t.Assert(s1.Len(), 4)
t.Assert(s1, []string{"a", "b", "c", "d"})
})
}
func TestSortedStrArray_SetArray(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"a", "d", "c", "b"}
a2 := []string{"f", "g", "h"}
array1 := garray.NewSortedStrArrayFrom(a1)
array1.SetArray(a2)
gtest.Assert(array1.Len(), 3)
gtest.Assert(array1.Contains("d"), false)
gtest.Assert(array1.Contains("b"), false)
gtest.Assert(array1.Contains("g"), true)
t.Assert(array1.Len(), 3)
t.Assert(array1.Contains("d"), false)
t.Assert(array1.Contains("b"), false)
t.Assert(array1.Contains("g"), true)
})
}
func TestSortedStrArray_Sort(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"a", "d", "c", "b"}
array1 := garray.NewSortedStrArrayFrom(a1)
gtest.Assert(array1, []string{"a", "b", "c", "d"})
t.Assert(array1, []string{"a", "b", "c", "d"})
array1.Sort()
gtest.Assert(array1.Len(), 4)
gtest.Assert(array1.Contains("c"), true)
gtest.Assert(array1, []string{"a", "b", "c", "d"})
t.Assert(array1.Len(), 4)
t.Assert(array1.Contains("c"), true)
t.Assert(array1, []string{"a", "b", "c", "d"})
})
}
func TestSortedStrArray_Get(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"a", "d", "c", "b"}
array1 := garray.NewSortedStrArrayFrom(a1)
gtest.Assert(array1.Get(2), "c")
gtest.Assert(array1.Get(0), "a")
t.Assert(array1.Get(2), "c")
t.Assert(array1.Get(0), "a")
})
}
func TestSortedStrArray_Remove(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"a", "d", "c", "b"}
array1 := garray.NewSortedStrArrayFrom(a1)
gtest.Assert(array1.Remove(-1), "")
gtest.Assert(array1.Remove(100000), "")
t.Assert(array1.Remove(-1), "")
t.Assert(array1.Remove(100000), "")
gtest.Assert(array1.Remove(2), "c")
gtest.Assert(array1.Get(2), "d")
gtest.Assert(array1.Len(), 3)
gtest.Assert(array1.Contains("c"), false)
t.Assert(array1.Remove(2), "c")
t.Assert(array1.Get(2), "d")
t.Assert(array1.Len(), 3)
t.Assert(array1.Contains("c"), false)
gtest.Assert(array1.Remove(0), "a")
gtest.Assert(array1.Len(), 2)
gtest.Assert(array1.Contains("a"), false)
t.Assert(array1.Remove(0), "a")
t.Assert(array1.Len(), 2)
t.Assert(array1.Contains("a"), false)
// 此时array1里的元素只剩下2个
gtest.Assert(array1.Remove(1), "d")
gtest.Assert(array1.Len(), 1)
t.Assert(array1.Remove(1), "d")
t.Assert(array1.Len(), 1)
})
}
func TestSortedStrArray_PopLeft(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d", "c", "b"}
array1 := garray.NewSortedStrArrayFrom(a1)
s1 := array1.PopLeft()
gtest.Assert(s1, "a")
gtest.Assert(array1.Len(), 4)
gtest.Assert(array1.Contains("a"), false)
t.Assert(s1, "a")
t.Assert(array1.Len(), 4)
t.Assert(array1.Contains("a"), false)
})
}
func TestSortedStrArray_PopRight(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d", "c", "b"}
array1 := garray.NewSortedStrArrayFrom(a1)
s1 := array1.PopRight()
gtest.Assert(s1, "e")
gtest.Assert(array1.Len(), 4)
gtest.Assert(array1.Contains("e"), false)
t.Assert(s1, "e")
t.Assert(array1.Len(), 4)
t.Assert(array1.Contains("e"), false)
})
}
func TestSortedStrArray_PopRand(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d", "c", "b"}
array1 := garray.NewSortedStrArrayFrom(a1)
s1 := array1.PopRand()
gtest.AssertIN(s1, []string{"e", "a", "d", "c", "b"})
gtest.Assert(array1.Len(), 4)
gtest.Assert(array1.Contains(s1), false)
t.AssertIN(s1, []string{"e", "a", "d", "c", "b"})
t.Assert(array1.Len(), 4)
t.Assert(array1.Contains(s1), false)
})
}
func TestSortedStrArray_PopRands(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d", "c", "b"}
array1 := garray.NewSortedStrArrayFrom(a1)
s1 := array1.PopRands(2)
gtest.AssertIN(s1, []string{"e", "a", "d", "c", "b"})
gtest.Assert(array1.Len(), 3)
gtest.Assert(len(s1), 2)
t.AssertIN(s1, []string{"e", "a", "d", "c", "b"})
t.Assert(array1.Len(), 3)
t.Assert(len(s1), 2)
s1 = array1.PopRands(4)
gtest.Assert(len(s1), 3)
gtest.AssertIN(s1, []string{"e", "a", "d", "c", "b"})
t.Assert(len(s1), 3)
t.AssertIN(s1, []string{"e", "a", "d", "c", "b"})
})
}
func TestSortedStrArray_Empty(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedStrArray()
t.Assert(array.PopLeft(), nil)
t.Assert(array.PopLefts(10), nil)
t.Assert(array.PopRight(), nil)
t.Assert(array.PopRights(10), nil)
t.Assert(array.PopRand(), nil)
t.Assert(array.PopRands(10), nil)
})
}
func TestSortedStrArray_PopLefts(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d", "c", "b"}
array1 := garray.NewSortedStrArrayFrom(a1)
s1 := array1.PopLefts(2)
gtest.Assert(s1, []string{"a", "b"})
gtest.Assert(array1.Len(), 3)
gtest.Assert(len(s1), 2)
t.Assert(s1, []string{"a", "b"})
t.Assert(array1.Len(), 3)
t.Assert(len(s1), 2)
s1 = array1.PopLefts(4)
gtest.Assert(len(s1), 3)
gtest.Assert(s1, []string{"c", "d", "e"})
t.Assert(len(s1), 3)
t.Assert(s1, []string{"c", "d", "e"})
})
}
func TestSortedStrArray_PopRights(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d", "c", "b", "f", "g"}
array1 := garray.NewSortedStrArrayFrom(a1)
s1 := array1.PopRights(2)
gtest.Assert(s1, []string{"f", "g"})
gtest.Assert(array1.Len(), 5)
gtest.Assert(len(s1), 2)
t.Assert(s1, []string{"f", "g"})
t.Assert(array1.Len(), 5)
t.Assert(len(s1), 2)
s1 = array1.PopRights(6)
gtest.Assert(len(s1), 5)
gtest.Assert(s1, []string{"a", "b", "c", "d", "e"})
gtest.Assert(array1.Len(), 0)
t.Assert(len(s1), 5)
t.Assert(s1, []string{"a", "b", "c", "d", "e"})
t.Assert(array1.Len(), 0)
})
}
func TestSortedStrArray_Range(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d", "c", "b", "f", "g"}
array1 := garray.NewSortedStrArrayFrom(a1)
array2 := garray.NewSortedStrArrayFrom(a1, true)
s1 := array1.Range(2, 4)
gtest.Assert(len(s1), 2)
gtest.Assert(s1, []string{"c", "d"})
t.Assert(len(s1), 2)
t.Assert(s1, []string{"c", "d"})
s1 = array1.Range(-1, 2)
gtest.Assert(len(s1), 2)
gtest.Assert(s1, []string{"a", "b"})
t.Assert(len(s1), 2)
t.Assert(s1, []string{"a", "b"})
s1 = array1.Range(4, 8)
gtest.Assert(len(s1), 3)
gtest.Assert(s1, []string{"e", "f", "g"})
gtest.Assert(array1.Range(10, 2), nil)
t.Assert(len(s1), 3)
t.Assert(s1, []string{"e", "f", "g"})
t.Assert(array1.Range(10, 2), nil)
s2 := array2.Range(2, 4)
gtest.Assert(s2, []string{"c", "d"})
t.Assert(s2, []string{"c", "d"})
})
}
func TestSortedStrArray_Sum(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d", "c", "b", "f", "g"}
a2 := []string{"1", "2", "3", "4", "a"}
array1 := garray.NewSortedStrArrayFrom(a1)
array2 := garray.NewSortedStrArrayFrom(a2)
gtest.Assert(array1.Sum(), 0)
gtest.Assert(array2.Sum(), 10)
t.Assert(array1.Sum(), 0)
t.Assert(array2.Sum(), 10)
})
}
func TestSortedStrArray_Clone(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d", "c", "b", "f", "g"}
array1 := garray.NewSortedStrArrayFrom(a1)
array2 := array1.Clone()
gtest.Assert(array1, array2)
t.Assert(array1, array2)
array1.Remove(1)
gtest.Assert(array2.Len(), 7)
t.Assert(array2.Len(), 7)
})
}
func TestSortedStrArray_Clear(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d", "c", "b", "f", "g"}
array1 := garray.NewSortedStrArrayFrom(a1)
array1.Clear()
gtest.Assert(array1.Len(), 0)
t.Assert(array1.Len(), 0)
})
}
func TestSortedStrArray_SubSlice(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d", "c", "b", "f", "g"}
array1 := garray.NewSortedStrArrayFrom(a1)
array2 := garray.NewSortedStrArrayFrom(a1, true)
s1 := array1.SubSlice(1, 3)
gtest.Assert(len(s1), 3)
gtest.Assert(s1, []string{"b", "c", "d"})
gtest.Assert(array1.Len(), 7)
t.Assert(len(s1), 3)
t.Assert(s1, []string{"b", "c", "d"})
t.Assert(array1.Len(), 7)
s2 := array1.SubSlice(1, 10)
gtest.Assert(len(s2), 6)
t.Assert(len(s2), 6)
s3 := array1.SubSlice(10, 2)
gtest.Assert(len(s3), 0)
t.Assert(len(s3), 0)
s3 = array1.SubSlice(-5, 2)
gtest.Assert(s3, []string{"c", "d"})
t.Assert(s3, []string{"c", "d"})
s3 = array1.SubSlice(-10, 2)
gtest.Assert(s3, nil)
t.Assert(s3, nil)
s3 = array1.SubSlice(1, -2)
gtest.Assert(s3, nil)
t.Assert(s3, nil)
gtest.Assert(array2.SubSlice(1, 3), []string{"b", "c", "d"})
t.Assert(array2.SubSlice(1, 3), []string{"b", "c", "d"})
})
}
func TestSortedStrArray_Len(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d", "c", "b", "f", "g"}
array1 := garray.NewSortedStrArrayFrom(a1)
gtest.Assert(array1.Len(), 7)
t.Assert(array1.Len(), 7)
})
}
func TestSortedStrArray_Rand(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d"}
array1 := garray.NewSortedStrArrayFrom(a1)
gtest.AssertIN(array1.Rand(), []string{"e", "a", "d"})
t.AssertIN(array1.Rand(), []string{"e", "a", "d"})
})
}
func TestSortedStrArray_Rands(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d"}
array1 := garray.NewSortedStrArrayFrom(a1)
s1 := array1.Rands(2)
gtest.AssertIN(s1, []string{"e", "a", "d"})
gtest.Assert(len(s1), 2)
t.AssertIN(s1, []string{"e", "a", "d"})
t.Assert(len(s1), 2)
s1 = array1.Rands(4)
gtest.AssertIN(s1, []string{"e", "a", "d"})
gtest.Assert(len(s1), 3)
t.AssertIN(s1, []string{"e", "a", "d"})
t.Assert(len(s1), 3)
})
}
func TestSortedStrArray_Join(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d"}
array1 := garray.NewSortedStrArrayFrom(a1)
gtest.Assert(array1.Join(","), `a,d,e`)
gtest.Assert(array1.Join("."), `a.d.e`)
t.Assert(array1.Join(","), `a,d,e`)
t.Assert(array1.Join("."), `a.d.e`)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"a", `"b"`, `\c`}
array1 := garray.NewSortedStrArrayFrom(a1)
gtest.Assert(array1.Join("."), `"b".\c.a`)
t.Assert(array1.Join("."), `"b".\c.a`)
})
}
func TestSortedStrArray_String(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d"}
array1 := garray.NewSortedStrArrayFrom(a1)
gtest.Assert(array1.String(), `["a","d","e"]`)
t.Assert(array1.String(), `["a","d","e"]`)
})
}
func TestSortedStrArray_CountValues(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d", "a", "c"}
array1 := garray.NewSortedStrArrayFrom(a1)
m1 := array1.CountValues()
gtest.Assert(m1["a"], 2)
gtest.Assert(m1["d"], 1)
t.Assert(m1["a"], 2)
t.Assert(m1["d"], 1)
})
}
func TestSortedStrArray_Chunk(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d", "a", "c"}
array1 := garray.NewSortedStrArrayFrom(a1)
array2 := array1.Chunk(2)
gtest.Assert(len(array2), 3)
gtest.Assert(len(array2[0]), 2)
gtest.Assert(array2[1], []string{"c", "d"})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(array2), 3)
t.Assert(len(array2[0]), 2)
t.Assert(array2[1], []string{"c", "d"})
t.Assert(array1.Chunk(0), nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"1", "2", "3", "4", "5"}
array1 := garray.NewSortedStrArrayFrom(a1)
chunks := array1.Chunk(3)
gtest.Assert(len(chunks), 2)
gtest.Assert(chunks[0], []string{"1", "2", "3"})
gtest.Assert(chunks[1], []string{"4", "5"})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 2)
t.Assert(chunks[0], []string{"1", "2", "3"})
t.Assert(chunks[1], []string{"4", "5"})
t.Assert(array1.Chunk(0), nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"1", "2", "3", "4", "5", "6"}
array1 := garray.NewSortedStrArrayFrom(a1)
chunks := array1.Chunk(2)
gtest.Assert(len(chunks), 3)
gtest.Assert(chunks[0], []string{"1", "2"})
gtest.Assert(chunks[1], []string{"3", "4"})
gtest.Assert(chunks[2], []string{"5", "6"})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 3)
t.Assert(chunks[0], []string{"1", "2"})
t.Assert(chunks[1], []string{"3", "4"})
t.Assert(chunks[2], []string{"5", "6"})
t.Assert(array1.Chunk(0), nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"1", "2", "3", "4", "5", "6"}
array1 := garray.NewSortedStrArrayFrom(a1)
chunks := array1.Chunk(3)
gtest.Assert(len(chunks), 2)
gtest.Assert(chunks[0], []string{"1", "2", "3"})
gtest.Assert(chunks[1], []string{"4", "5", "6"})
gtest.Assert(array1.Chunk(0), nil)
t.Assert(len(chunks), 2)
t.Assert(chunks[0], []string{"1", "2", "3"})
t.Assert(chunks[1], []string{"4", "5", "6"})
t.Assert(array1.Chunk(0), nil)
})
}
func TestSortedStrArray_SetUnique(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a1 := []string{"e", "a", "d", "a", "c"}
array1 := garray.NewSortedStrArrayFrom(a1)
array2 := array1.SetUnique(true)
gtest.Assert(array2.Len(), 4)
gtest.Assert(array2, []string{"a", "c", "d", "e"})
t.Assert(array2.Len(), 4)
t.Assert(array2, []string{"a", "c", "d", "e"})
})
}
func TestSortedStrArray_LockFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []string{"a", "b", "c", "d"}
a1 := garray.NewSortedStrArrayFrom(s1, true)
@ -401,13 +413,13 @@ func TestSortedStrArray_LockFunc(t *testing.T) {
<-ch2 //等待go1完成
// 防止ci抖动,以豪秒为单位
gtest.AssertGT(t2-t1, 20) //go1加的读写互斥锁所go2读的时候被阻塞。
gtest.Assert(a1.Contains("g"), true)
t.AssertGT(t2-t1, 20) //go1加的读写互斥锁所go2读的时候被阻塞。
t.Assert(a1.Contains("g"), true)
})
}
func TestSortedStrArray_RLockFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []string{"a", "b", "c", "d"}
a1 := garray.NewSortedStrArrayFrom(s1, true)
@ -433,13 +445,13 @@ func TestSortedStrArray_RLockFunc(t *testing.T) {
<-ch2 //等待go1完成
// 防止ci抖动,以豪秒为单位
gtest.AssertLT(t2-t1, 20) //go1加的读锁所go2读的时候并没有阻塞。
gtest.Assert(a1.Contains("g"), true)
t.AssertLT(t2-t1, 20) //go1加的读锁所go2读的时候并没有阻塞。
t.Assert(a1.Contains("g"), true)
})
}
func TestSortedStrArray_Merge(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
func1 := func(v1, v2 interface{}) int {
if gconv.Int(v1) < gconv.Int(v2) {
return 0
@ -457,39 +469,39 @@ func TestSortedStrArray_Merge(t *testing.T) {
s6 := garray.NewSortedIntArrayFrom([]int{1, 2, 3})
a1 := garray.NewSortedStrArrayFrom(s1)
gtest.Assert(a1.Merge(s2).Len(), 6)
gtest.Assert(a1.Merge(i1).Len(), 9)
gtest.Assert(a1.Merge(i2).Len(), 10)
gtest.Assert(a1.Merge(s3).Len(), 12)
gtest.Assert(a1.Merge(s4).Len(), 14)
gtest.Assert(a1.Merge(s5).Len(), 16)
gtest.Assert(a1.Merge(s6).Len(), 19)
t.Assert(a1.Merge(s2).Len(), 6)
t.Assert(a1.Merge(i1).Len(), 9)
t.Assert(a1.Merge(i2).Len(), 10)
t.Assert(a1.Merge(s3).Len(), 12)
t.Assert(a1.Merge(s4).Len(), 14)
t.Assert(a1.Merge(s5).Len(), 16)
t.Assert(a1.Merge(s6).Len(), 19)
})
}
func TestSortedStrArray_Json(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []string{"a", "b", "d", "c"}
s2 := []string{"a", "b", "c", "d"}
a1 := garray.NewSortedStrArrayFrom(s1)
b1, err1 := json.Marshal(a1)
b2, err2 := json.Marshal(s1)
gtest.Assert(b1, b2)
gtest.Assert(err1, err2)
t.Assert(b1, b2)
t.Assert(err1, err2)
a2 := garray.NewSortedStrArray()
err1 = json.Unmarshal(b2, &a2)
gtest.Assert(a2.Slice(), s2)
gtest.Assert(a2.Interfaces(), s2)
t.Assert(a2.Slice(), s2)
t.Assert(a2.Interfaces(), s2)
var a3 garray.SortedStrArray
err := json.Unmarshal(b2, &a3)
gtest.Assert(err, nil)
gtest.Assert(a3.Slice(), s1)
gtest.Assert(a3.Interfaces(), s1)
t.Assert(err, nil)
t.Assert(a3.Slice(), s1)
t.Assert(a3.Interfaces(), s1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
type User struct {
Name string
Scores *garray.SortedStrArray
@ -499,111 +511,111 @@ func TestSortedStrArray_Json(t *testing.T) {
"Scores": []string{"A+", "A", "A"},
}
b, err := json.Marshal(data)
gtest.Assert(err, nil)
t.Assert(err, nil)
user := new(User)
err = json.Unmarshal(b, user)
gtest.Assert(err, nil)
gtest.Assert(user.Name, data["Name"])
gtest.Assert(user.Scores, []string{"A", "A", "A+"})
t.Assert(err, nil)
t.Assert(user.Name, data["Name"])
t.Assert(user.Scores, []string{"A", "A", "A+"})
})
}
func TestSortedStrArray_Iterator(t *testing.T) {
slice := g.SliceStr{"a", "b", "d", "c"}
array := garray.NewSortedStrArrayFrom(slice)
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.Iterator(func(k int, v string) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.IteratorAsc(func(k int, v string) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array.IteratorDesc(func(k int, v string) bool {
gtest.Assert(v, slice[k])
t.Assert(v, slice[k])
return true
})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.Iterator(func(k int, v string) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.IteratorAsc(func(k int, v string) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
index := 0
array.IteratorDesc(func(k int, v string) bool {
index++
return false
})
gtest.Assert(index, 1)
t.Assert(index, 1)
})
}
func TestSortedStrArray_RemoveValue(t *testing.T) {
slice := g.SliceStr{"a", "b", "d", "c"}
array := garray.NewSortedStrArrayFrom(slice)
gtest.Case(t, func() {
gtest.Assert(array.RemoveValue("e"), false)
gtest.Assert(array.RemoveValue("b"), true)
gtest.Assert(array.RemoveValue("a"), true)
gtest.Assert(array.RemoveValue("c"), true)
gtest.Assert(array.RemoveValue("f"), false)
gtest.C(t, func(t *gtest.T) {
t.Assert(array.RemoveValue("e"), false)
t.Assert(array.RemoveValue("b"), true)
t.Assert(array.RemoveValue("a"), true)
t.Assert(array.RemoveValue("c"), true)
t.Assert(array.RemoveValue("f"), false)
})
}
func TestSortedStrArray_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Array *garray.SortedStrArray
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": []byte(`["1","3","2"]`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Array.Slice(), g.SliceStr{"1", "2", "3"})
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Array.Slice(), g.SliceStr{"1", "2", "3"})
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": g.SliceStr{"1", "3", "2"},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Array.Slice(), g.SliceStr{"1", "2", "3"})
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Array.Slice(), g.SliceStr{"1", "2", "3"})
})
}
func TestSortedStrArray_FilterEmpty(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedStrArrayFrom(g.SliceStr{"", "1", "2", "0"})
gtest.Assert(array.FilterEmpty(), g.SliceStr{"0", "1", "2"})
t.Assert(array.FilterEmpty(), g.SliceStr{"0", "1", "2"})
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedStrArrayFrom(g.SliceStr{"1", "2"})
gtest.Assert(array.FilterEmpty(), g.SliceStr{"1", "2"})
t.Assert(array.FilterEmpty(), g.SliceStr{"1", "2"})
})
}

View File

@ -9,18 +9,18 @@ import (
)
func Test_Gchan(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
ch := gchan.New(10)
gtest.Assert(ch.Cap(), 10)
gtest.Assert(ch.Push(1), nil)
gtest.Assert(ch.Len(), 1)
gtest.Assert(ch.Size(), 1)
t.Assert(ch.Cap(), 10)
t.Assert(ch.Push(1), nil)
t.Assert(ch.Len(), 1)
t.Assert(ch.Size(), 1)
ch.Pop()
gtest.Assert(ch.Len(), 0)
gtest.Assert(ch.Size(), 0)
t.Assert(ch.Len(), 0)
t.Assert(ch.Size(), 0)
ch.Close()
gtest.Assert(ch.Push(1), errors.New("channel is closed"))
t.Assert(ch.Push(1), errors.New("channel is closed"))
ch = gchan.New(0)
ch1 := gchan.New(0)
@ -32,7 +32,7 @@ func Test_Gchan(t *testing.T) {
ch1.Push(i)
break
}
gtest.Assert(v, i)
t.Assert(v, i)
i++
}
}()
@ -41,7 +41,7 @@ func Test_Gchan(t *testing.T) {
ch.Push(index)
}
ch.Close()
gtest.Assert(ch1.Pop(), 10)
t.Assert(ch1.Pop(), 10)
ch1.Close()
})
}

View File

@ -16,7 +16,7 @@ import (
)
// 检查链表长度
func checkListLen(t *testing.T, l *List, len int) bool {
func checkListLen(t *gtest.T, l *List, len int) bool {
if n := l.Len(); n != len {
t.Errorf("l.Len() = %d, want %d", n, len)
return false
@ -25,7 +25,7 @@ func checkListLen(t *testing.T, l *List, len int) bool {
}
// 检查指针地址
func checkListPointers(t *testing.T, l *List, es []*Element) {
func checkListPointers(t *gtest.T, l *List, es []*Element) {
if !checkListLen(t, l, len(es)) {
return
}
@ -80,87 +80,89 @@ func TestBasic(t *testing.T) {
}
func TestList(t *testing.T) {
l := New()
checkListPointers(t, l, []*Element{})
gtest.C(t, func(t *gtest.T) {
l := New()
checkListPointers(t, l, []*Element{})
// Single element list
e := l.PushFront("a")
checkListPointers(t, l, []*Element{e})
l.MoveToFront(e)
checkListPointers(t, l, []*Element{e})
l.MoveToBack(e)
checkListPointers(t, l, []*Element{e})
l.Remove(e)
checkListPointers(t, l, []*Element{})
// Bigger list
e2 := l.PushFront(2)
e1 := l.PushFront(1)
e3 := l.PushBack(3)
e4 := l.PushBack("banana")
checkListPointers(t, l, []*Element{e1, e2, e3, e4})
l.Remove(e2)
checkListPointers(t, l, []*Element{e1, e3, e4})
l.MoveToFront(e3) // move from middle
checkListPointers(t, l, []*Element{e3, e1, e4})
l.MoveToFront(e1)
l.MoveToBack(e3) // move from middle
checkListPointers(t, l, []*Element{e1, e4, e3})
l.MoveToFront(e3) // move from back
checkListPointers(t, l, []*Element{e3, e1, e4})
l.MoveToFront(e3) // should be no-op
checkListPointers(t, l, []*Element{e3, e1, e4})
l.MoveToBack(e3) // move from front
checkListPointers(t, l, []*Element{e1, e4, e3})
l.MoveToBack(e3) // should be no-op
checkListPointers(t, l, []*Element{e1, e4, e3})
e2 = l.InsertBefore(e1, 2) // insert before front
checkListPointers(t, l, []*Element{e2, e1, e4, e3})
l.Remove(e2)
e2 = l.InsertBefore(e4, 2) // insert before middle
checkListPointers(t, l, []*Element{e1, e2, e4, e3})
l.Remove(e2)
e2 = l.InsertBefore(e3, 2) // insert before back
checkListPointers(t, l, []*Element{e1, e4, e2, e3})
l.Remove(e2)
e2 = l.InsertAfter(e1, 2) // insert after front
checkListPointers(t, l, []*Element{e1, e2, e4, e3})
l.Remove(e2)
e2 = l.InsertAfter(e4, 2) // insert after middle
checkListPointers(t, l, []*Element{e1, e4, e2, e3})
l.Remove(e2)
e2 = l.InsertAfter(e3, 2) // insert after back
checkListPointers(t, l, []*Element{e1, e4, e3, e2})
l.Remove(e2)
// Check standard iteration.
sum := 0
for e := l.Front(); e != nil; e = e.Next() {
if i, ok := e.Value.(int); ok {
sum += i
}
}
if sum != 4 {
t.Errorf("sum over l = %d, want 4", sum)
}
// Clear all elements by iterating
var next *Element
for e := l.Front(); e != nil; e = next {
next = e.Next()
// Single element list
e := l.PushFront("a")
checkListPointers(t, l, []*Element{e})
l.MoveToFront(e)
checkListPointers(t, l, []*Element{e})
l.MoveToBack(e)
checkListPointers(t, l, []*Element{e})
l.Remove(e)
}
checkListPointers(t, l, []*Element{})
checkListPointers(t, l, []*Element{})
// Bigger list
e2 := l.PushFront(2)
e1 := l.PushFront(1)
e3 := l.PushBack(3)
e4 := l.PushBack("banana")
checkListPointers(t, l, []*Element{e1, e2, e3, e4})
l.Remove(e2)
checkListPointers(t, l, []*Element{e1, e3, e4})
l.MoveToFront(e3) // move from middle
checkListPointers(t, l, []*Element{e3, e1, e4})
l.MoveToFront(e1)
l.MoveToBack(e3) // move from middle
checkListPointers(t, l, []*Element{e1, e4, e3})
l.MoveToFront(e3) // move from back
checkListPointers(t, l, []*Element{e3, e1, e4})
l.MoveToFront(e3) // should be no-op
checkListPointers(t, l, []*Element{e3, e1, e4})
l.MoveToBack(e3) // move from front
checkListPointers(t, l, []*Element{e1, e4, e3})
l.MoveToBack(e3) // should be no-op
checkListPointers(t, l, []*Element{e1, e4, e3})
e2 = l.InsertBefore(e1, 2) // insert before front
checkListPointers(t, l, []*Element{e2, e1, e4, e3})
l.Remove(e2)
e2 = l.InsertBefore(e4, 2) // insert before middle
checkListPointers(t, l, []*Element{e1, e2, e4, e3})
l.Remove(e2)
e2 = l.InsertBefore(e3, 2) // insert before back
checkListPointers(t, l, []*Element{e1, e4, e2, e3})
l.Remove(e2)
e2 = l.InsertAfter(e1, 2) // insert after front
checkListPointers(t, l, []*Element{e1, e2, e4, e3})
l.Remove(e2)
e2 = l.InsertAfter(e4, 2) // insert after middle
checkListPointers(t, l, []*Element{e1, e4, e2, e3})
l.Remove(e2)
e2 = l.InsertAfter(e3, 2) // insert after back
checkListPointers(t, l, []*Element{e1, e4, e3, e2})
l.Remove(e2)
// Check standard iteration.
sum := 0
for e := l.Front(); e != nil; e = e.Next() {
if i, ok := e.Value.(int); ok {
sum += i
}
}
if sum != 4 {
t.Errorf("sum over l = %d, want 4", sum)
}
// Clear all elements by iterating
var next *Element
for e := l.Front(); e != nil; e = next {
next = e.Next()
l.Remove(e)
}
checkListPointers(t, l, []*Element{})
})
}
func checkList(t *testing.T, l *List, es []interface{}) {
func checkList(t *gtest.T, l *List, es []interface{}) {
if !checkListLen(t, l, len(es)) {
return
}
@ -193,60 +195,64 @@ func checkList(t *testing.T, l *List, es []interface{}) {
}
func TestExtending(t *testing.T) {
l1 := New()
l2 := New()
gtest.C(t, func(t *gtest.T) {
l1 := New()
l2 := New()
l1.PushBack(1)
l1.PushBack(2)
l1.PushBack(3)
l1.PushBack(1)
l1.PushBack(2)
l1.PushBack(3)
l2.PushBack(4)
l2.PushBack(5)
l2.PushBack(4)
l2.PushBack(5)
l3 := New()
l3.PushBackList(l1)
checkList(t, l3, []interface{}{1, 2, 3})
l3.PushBackList(l2)
checkList(t, l3, []interface{}{1, 2, 3, 4, 5})
l3 := New()
l3.PushBackList(l1)
checkList(t, l3, []interface{}{1, 2, 3})
l3.PushBackList(l2)
checkList(t, l3, []interface{}{1, 2, 3, 4, 5})
l3 = New()
l3.PushFrontList(l2)
checkList(t, l3, []interface{}{4, 5})
l3.PushFrontList(l1)
checkList(t, l3, []interface{}{1, 2, 3, 4, 5})
l3 = New()
l3.PushFrontList(l2)
checkList(t, l3, []interface{}{4, 5})
l3.PushFrontList(l1)
checkList(t, l3, []interface{}{1, 2, 3, 4, 5})
checkList(t, l1, []interface{}{1, 2, 3})
checkList(t, l2, []interface{}{4, 5})
checkList(t, l1, []interface{}{1, 2, 3})
checkList(t, l2, []interface{}{4, 5})
l3 = New()
l3.PushBackList(l1)
checkList(t, l3, []interface{}{1, 2, 3})
l3.PushBackList(l3)
checkList(t, l3, []interface{}{1, 2, 3, 1, 2, 3})
l3 = New()
l3.PushBackList(l1)
checkList(t, l3, []interface{}{1, 2, 3})
l3.PushBackList(l3)
checkList(t, l3, []interface{}{1, 2, 3, 1, 2, 3})
l3 = New()
l3.PushFrontList(l1)
checkList(t, l3, []interface{}{1, 2, 3})
l3.PushFrontList(l3)
checkList(t, l3, []interface{}{1, 2, 3, 1, 2, 3})
l3 = New()
l3.PushFrontList(l1)
checkList(t, l3, []interface{}{1, 2, 3})
l3.PushFrontList(l3)
checkList(t, l3, []interface{}{1, 2, 3, 1, 2, 3})
l3 = New()
l1.PushBackList(l3)
checkList(t, l1, []interface{}{1, 2, 3})
l1.PushFrontList(l3)
checkList(t, l1, []interface{}{1, 2, 3})
l3 = New()
l1.PushBackList(l3)
checkList(t, l1, []interface{}{1, 2, 3})
l1.PushFrontList(l3)
checkList(t, l1, []interface{}{1, 2, 3})
})
}
func TestRemove(t *testing.T) {
l := New()
e1 := l.PushBack(1)
e2 := l.PushBack(2)
checkListPointers(t, l, []*Element{e1, e2})
//e := l.Front()
//l.Remove(e)
//checkListPointers(t, l, []*Element{e2})
//l.Remove(e)
//checkListPointers(t, l, []*Element{e2})
gtest.C(t, func(t *gtest.T) {
l := New()
e1 := l.PushBack(1)
e2 := l.PushBack(2)
checkListPointers(t, l, []*Element{e1, e2})
//e := l.Front()
//l.Remove(e)
//checkListPointers(t, l, []*Element{e2})
//l.Remove(e)
//checkListPointers(t, l, []*Element{e2})
})
}
func TestIssue4103(t *testing.T) {
@ -289,375 +295,416 @@ func TestIssue6349(t *testing.T) {
}
func TestMove(t *testing.T) {
l := New()
e1 := l.PushBack(1)
e2 := l.PushBack(2)
e3 := l.PushBack(3)
e4 := l.PushBack(4)
gtest.C(t, func(t *gtest.T) {
l := New()
e1 := l.PushBack(1)
e2 := l.PushBack(2)
e3 := l.PushBack(3)
e4 := l.PushBack(4)
l.MoveAfter(e3, e3)
checkListPointers(t, l, []*Element{e1, e2, e3, e4})
l.MoveBefore(e2, e2)
checkListPointers(t, l, []*Element{e1, e2, e3, e4})
l.MoveAfter(e3, e3)
checkListPointers(t, l, []*Element{e1, e2, e3, e4})
l.MoveBefore(e2, e2)
checkListPointers(t, l, []*Element{e1, e2, e3, e4})
l.MoveAfter(e3, e2)
checkListPointers(t, l, []*Element{e1, e2, e3, e4})
l.MoveBefore(e2, e3)
checkListPointers(t, l, []*Element{e1, e2, e3, e4})
l.MoveAfter(e3, e2)
checkListPointers(t, l, []*Element{e1, e2, e3, e4})
l.MoveBefore(e2, e3)
checkListPointers(t, l, []*Element{e1, e2, e3, e4})
l.MoveBefore(e2, e4)
checkListPointers(t, l, []*Element{e1, e3, e2, e4})
e2, e3 = e3, e2
l.MoveBefore(e2, e4)
checkListPointers(t, l, []*Element{e1, e3, e2, e4})
e2, e3 = e3, e2
l.MoveBefore(e4, e1)
checkListPointers(t, l, []*Element{e4, e1, e2, e3})
e1, e2, e3, e4 = e4, e1, e2, e3
l.MoveBefore(e4, e1)
checkListPointers(t, l, []*Element{e4, e1, e2, e3})
e1, e2, e3, e4 = e4, e1, e2, e3
l.MoveAfter(e4, e1)
checkListPointers(t, l, []*Element{e1, e4, e2, e3})
e2, e3, e4 = e4, e2, e3
l.MoveAfter(e4, e1)
checkListPointers(t, l, []*Element{e1, e4, e2, e3})
e2, e3, e4 = e4, e2, e3
l.MoveAfter(e2, e3)
checkListPointers(t, l, []*Element{e1, e3, e2, e4})
e2, e3 = e3, e2
l.MoveAfter(e2, e3)
checkListPointers(t, l, []*Element{e1, e3, e2, e4})
e2, e3 = e3, e2
})
}
// Test PushFront, PushBack, PushFrontList, PushBackList with uninitialized List
func TestZeroList(t *testing.T) {
var l1 = New()
l1.PushFront(1)
checkList(t, l1, []interface{}{1})
gtest.C(t, func(t *gtest.T) {
var l1 = New()
l1.PushFront(1)
checkList(t, l1, []interface{}{1})
var l2 = New()
l2.PushBack(1)
checkList(t, l2, []interface{}{1})
var l2 = New()
l2.PushBack(1)
checkList(t, l2, []interface{}{1})
var l3 = New()
l3.PushFrontList(l1)
checkList(t, l3, []interface{}{1})
var l3 = New()
l3.PushFrontList(l1)
checkList(t, l3, []interface{}{1})
var l4 = New()
l4.PushBackList(l2)
checkList(t, l4, []interface{}{1})
var l4 = New()
l4.PushBackList(l2)
checkList(t, l4, []interface{}{1})
})
}
// Test that a list l is not modified when calling InsertBefore with a mark that is not an element of l.
func TestInsertBeforeUnknownMark(t *testing.T) {
l := New()
l.PushBack(1)
l.PushBack(2)
l.PushBack(3)
l.InsertBefore(new(Element), 1)
checkList(t, l, []interface{}{1, 2, 3})
gtest.C(t, func(t *gtest.T) {
l := New()
l.PushBack(1)
l.PushBack(2)
l.PushBack(3)
l.InsertBefore(new(Element), 1)
checkList(t, l, []interface{}{1, 2, 3})
})
}
// Test that a list l is not modified when calling InsertAfter with a mark that is not an element of l.
func TestInsertAfterUnknownMark(t *testing.T) {
l := New()
l.PushBack(1)
l.PushBack(2)
l.PushBack(3)
l.InsertAfter(new(Element), 1)
checkList(t, l, []interface{}{1, 2, 3})
gtest.C(t, func(t *gtest.T) {
l := New()
l.PushBack(1)
l.PushBack(2)
l.PushBack(3)
l.InsertAfter(new(Element), 1)
checkList(t, l, []interface{}{1, 2, 3})
})
}
// Test that a list l is not modified when calling MoveAfter or MoveBefore with a mark that is not an element of l.
func TestMoveUnknownMark(t *testing.T) {
l1 := New()
e1 := l1.PushBack(1)
gtest.C(t, func(t *gtest.T) {
l1 := New()
e1 := l1.PushBack(1)
l2 := New()
e2 := l2.PushBack(2)
l2 := New()
e2 := l2.PushBack(2)
l1.MoveAfter(e1, e2)
checkList(t, l1, []interface{}{1})
checkList(t, l2, []interface{}{2})
l1.MoveAfter(e1, e2)
checkList(t, l1, []interface{}{1})
checkList(t, l2, []interface{}{2})
l1.MoveBefore(e1, e2)
checkList(t, l1, []interface{}{1})
checkList(t, l2, []interface{}{2})
l1.MoveBefore(e1, e2)
checkList(t, l1, []interface{}{1})
checkList(t, l2, []interface{}{2})
})
}
func TestList_RemoveAll(t *testing.T) {
l := New()
l.PushBack(1)
l.RemoveAll()
checkList(t, l, []interface{}{})
l.PushBack(2)
checkList(t, l, []interface{}{2})
gtest.C(t, func(t *gtest.T) {
l := New()
l.PushBack(1)
l.RemoveAll()
checkList(t, l, []interface{}{})
l.PushBack(2)
checkList(t, l, []interface{}{2})
})
}
func TestList_PushFronts(t *testing.T) {
l := New()
a1 := []interface{}{1, 2}
l.PushFronts(a1)
checkList(t, l, []interface{}{2, 1})
a1 = []interface{}{3, 4, 5}
l.PushFronts(a1)
checkList(t, l, []interface{}{5, 4, 3, 2, 1})
gtest.C(t, func(t *gtest.T) {
l := New()
a1 := []interface{}{1, 2}
l.PushFronts(a1)
checkList(t, l, []interface{}{2, 1})
a1 = []interface{}{3, 4, 5}
l.PushFronts(a1)
checkList(t, l, []interface{}{5, 4, 3, 2, 1})
})
}
func TestList_PushBacks(t *testing.T) {
l := New()
a1 := []interface{}{1, 2}
l.PushBacks(a1)
checkList(t, l, []interface{}{1, 2})
a1 = []interface{}{3, 4, 5}
l.PushBacks(a1)
checkList(t, l, []interface{}{1, 2, 3, 4, 5})
gtest.C(t, func(t *gtest.T) {
l := New()
a1 := []interface{}{1, 2}
l.PushBacks(a1)
checkList(t, l, []interface{}{1, 2})
a1 = []interface{}{3, 4, 5}
l.PushBacks(a1)
checkList(t, l, []interface{}{1, 2, 3, 4, 5})
})
}
func TestList_PopBacks(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
a2 := []interface{}{"a", "c", "b", "e"}
l.PushFronts(a1)
i1 := l.PopBacks(2)
gtest.Assert(i1, []interface{}{1, 2})
t.Assert(i1, []interface{}{1, 2})
l.PushBacks(a2) //4.3,a,c,b,e
i1 = l.PopBacks(3)
gtest.Assert(i1, []interface{}{"e", "b", "c"})
t.Assert(i1, []interface{}{"e", "b", "c"})
})
}
func TestList_PopFronts(t *testing.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
i1 := l.PopFronts(2)
gtest.Assert(i1, []interface{}{4, 3})
gtest.Assert(l.Len(), 2)
gtest.C(t, func(t *gtest.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
i1 := l.PopFronts(2)
t.Assert(i1, []interface{}{4, 3})
t.Assert(l.Len(), 2)
})
}
func TestList_PopBackAll(t *testing.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
i1 := l.PopBackAll()
gtest.Assert(i1, []interface{}{1, 2, 3, 4})
gtest.Assert(l.Len(), 0)
gtest.C(t, func(t *gtest.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
i1 := l.PopBackAll()
t.Assert(i1, []interface{}{1, 2, 3, 4})
t.Assert(l.Len(), 0)
})
}
func TestList_PopFrontAll(t *testing.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
i1 := l.PopFrontAll()
gtest.Assert(i1, []interface{}{4, 3, 2, 1})
gtest.Assert(l.Len(), 0)
gtest.C(t, func(t *gtest.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
i1 := l.PopFrontAll()
t.Assert(i1, []interface{}{4, 3, 2, 1})
t.Assert(l.Len(), 0)
})
}
func TestList_FrontAll(t *testing.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
i1 := l.FrontAll()
gtest.Assert(i1, []interface{}{4, 3, 2, 1})
gtest.Assert(l.Len(), 4)
gtest.C(t, func(t *gtest.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
i1 := l.FrontAll()
t.Assert(i1, []interface{}{4, 3, 2, 1})
t.Assert(l.Len(), 4)
})
}
func TestList_BackAll(t *testing.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
i1 := l.BackAll()
gtest.Assert(i1, []interface{}{1, 2, 3, 4})
gtest.Assert(l.Len(), 4)
gtest.C(t, func(t *gtest.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
i1 := l.BackAll()
t.Assert(i1, []interface{}{1, 2, 3, 4})
t.Assert(l.Len(), 4)
})
}
func TestList_FrontValue(t *testing.T) {
l := New()
l2 := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
i1 := l.FrontValue()
gtest.Assert(gconv.Int(i1), 4)
gtest.Assert(l.Len(), 4)
gtest.C(t, func(t *gtest.T) {
l := New()
l2 := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
i1 := l.FrontValue()
t.Assert(gconv.Int(i1), 4)
t.Assert(l.Len(), 4)
i1 = l2.FrontValue()
gtest.Assert(i1, nil)
i1 = l2.FrontValue()
t.Assert(i1, nil)
})
}
func TestList_BackValue(t *testing.T) {
l := New()
l2 := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
i1 := l.BackValue()
gtest.Assert(gconv.Int(i1), 1)
gtest.Assert(l.Len(), 4)
i1 = l2.FrontValue()
gtest.Assert(i1, nil)
gtest.C(t, func(t *gtest.T) {
l := New()
l2 := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
i1 := l.BackValue()
t.Assert(gconv.Int(i1), 1)
t.Assert(l.Len(), 4)
i1 = l2.FrontValue()
t.Assert(i1, nil)
})
}
func TestList_Back(t *testing.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
e1 := l.Back()
gtest.Assert(e1.Value, 1)
gtest.Assert(l.Len(), 4)
gtest.C(t, func(t *gtest.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
e1 := l.Back()
t.Assert(e1.Value, 1)
t.Assert(l.Len(), 4)
})
}
func TestList_Size(t *testing.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
gtest.Assert(l.Size(), 4)
l.PopFront()
gtest.Assert(l.Size(), 3)
gtest.C(t, func(t *gtest.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
t.Assert(l.Size(), 4)
l.PopFront()
t.Assert(l.Size(), 3)
})
}
func TestList_Removes(t *testing.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
e1 := l.Back()
l.Removes([]*Element{e1})
gtest.Assert(l.Len(), 3)
e2 := l.Back()
l.Removes([]*Element{e2})
gtest.Assert(l.Len(), 2)
checkList(t, l, []interface{}{4, 3})
gtest.C(t, func(t *gtest.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
e1 := l.Back()
l.Removes([]*Element{e1})
t.Assert(l.Len(), 3)
e2 := l.Back()
l.Removes([]*Element{e2})
t.Assert(l.Len(), 2)
checkList(t, l, []interface{}{4, 3})
})
}
func TestList_Clear(t *testing.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
l.Clear()
gtest.Assert(l.Len(), 0)
gtest.C(t, func(t *gtest.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
l.Clear()
t.Assert(l.Len(), 0)
})
}
func TestList_IteratorAsc(t *testing.T) {
l := New()
a1 := []interface{}{1, 2, 5, 6, 3, 4}
l.PushFronts(a1)
e1 := l.Back()
fun1 := func(e *Element) bool {
if gconv.Int(e1.Value) > 2 {
return true
gtest.C(t, func(t *gtest.T) {
l := New()
a1 := []interface{}{1, 2, 5, 6, 3, 4}
l.PushFronts(a1)
e1 := l.Back()
fun1 := func(e *Element) bool {
if gconv.Int(e1.Value) > 2 {
return true
}
return false
}
return false
}
checkList(t, l, []interface{}{4, 3, 6, 5, 2, 1})
l.IteratorAsc(fun1)
checkList(t, l, []interface{}{4, 3, 6, 5, 2, 1})
checkList(t, l, []interface{}{4, 3, 6, 5, 2, 1})
l.IteratorAsc(fun1)
checkList(t, l, []interface{}{4, 3, 6, 5, 2, 1})
})
}
func TestList_IteratorDesc(t *testing.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
e1 := l.Back()
fun1 := func(e *Element) bool {
if gconv.Int(e1.Value) > 6 {
return true
gtest.C(t, func(t *gtest.T) {
l := New()
a1 := []interface{}{1, 2, 3, 4}
l.PushFronts(a1)
e1 := l.Back()
fun1 := func(e *Element) bool {
if gconv.Int(e1.Value) > 6 {
return true
}
return false
}
return false
}
l.IteratorDesc(fun1)
gtest.Assert(l.Len(), 4)
checkList(t, l, []interface{}{4, 3, 2, 1})
l.IteratorDesc(fun1)
t.Assert(l.Len(), 4)
checkList(t, l, []interface{}{4, 3, 2, 1})
})
}
func TestList_Iterator(t *testing.T) {
l := New()
a1 := []interface{}{"a", "b", "c", "d", "e"}
l.PushFronts(a1)
e1 := l.Back()
fun1 := func(e *Element) bool {
if gconv.String(e1.Value) > "c" {
return true
gtest.C(t, func(t *gtest.T) {
l := New()
a1 := []interface{}{"a", "b", "c", "d", "e"}
l.PushFronts(a1)
e1 := l.Back()
fun1 := func(e *Element) bool {
if gconv.String(e1.Value) > "c" {
return true
}
return false
}
return false
}
checkList(t, l, []interface{}{"e", "d", "c", "b", "a"})
l.Iterator(fun1)
checkList(t, l, []interface{}{"e", "d", "c", "b", "a"})
checkList(t, l, []interface{}{"e", "d", "c", "b", "a"})
l.Iterator(fun1)
checkList(t, l, []interface{}{"e", "d", "c", "b", "a"})
})
}
func TestList_Join(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
l := NewFrom([]interface{}{1, 2, "a", `"b"`, `\c`})
gtest.Assert(l.Join(","), `1,2,"a","\"b\"","\\c"`)
gtest.Assert(l.Join("."), `1.2."a"."\"b\""."\\c"`)
t.Assert(l.Join(","), `1,2,"a","\"b\"","\\c"`)
t.Assert(l.Join("."), `1.2."a"."\"b\""."\\c"`)
})
}
func TestList_String(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
l := NewFrom([]interface{}{1, 2, "a", `"b"`, `\c`})
gtest.Assert(l.String(), `[1,2,"a","\"b\"","\\c"]`)
t.Assert(l.String(), `[1,2,"a","\"b\"","\\c"]`)
})
}
func TestList_Json(t *testing.T) {
// Marshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a := []interface{}{"a", "b", "c"}
l := New()
l.PushBacks(a)
b1, err1 := json.Marshal(l)
b2, err2 := json.Marshal(a)
gtest.Assert(err1, err2)
gtest.Assert(b1, b2)
t.Assert(err1, err2)
t.Assert(b1, b2)
})
// Unmarshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a := []interface{}{"a", "b", "c"}
l := New()
b, err := json.Marshal(a)
gtest.Assert(err, nil)
t.Assert(err, nil)
err = json.Unmarshal(b, l)
gtest.Assert(err, nil)
gtest.Assert(l.FrontAll(), a)
t.Assert(err, nil)
t.Assert(l.FrontAll(), a)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var l List
a := []interface{}{"a", "b", "c"}
b, err := json.Marshal(a)
gtest.Assert(err, nil)
t.Assert(err, nil)
err = json.Unmarshal(b, &l)
gtest.Assert(err, nil)
gtest.Assert(l.FrontAll(), a)
t.Assert(err, nil)
t.Assert(l.FrontAll(), a)
})
}
func TestList_UnmarshalValue(t *testing.T) {
type T struct {
type TList struct {
Name string
List *List
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var tlist *TList
err := gconv.Struct(map[string]interface{}{
"name": "john",
"list": []byte(`[1,2,3]`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.List.FrontAll(), []interface{}{1, 2, 3})
}, &tlist)
t.Assert(err, nil)
t.Assert(tlist.Name, "john")
t.Assert(tlist.List.FrontAll(), []interface{}{1, 2, 3})
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var tlist *TList
err := gconv.Struct(map[string]interface{}{
"name": "john",
"list": []interface{}{1, 2, 3},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.List.FrontAll(), []interface{}{1, 2, 3})
}, &tlist)
t.Assert(err, nil)
t.Assert(tlist.Name, "john")
t.Assert(tlist.List.FrontAll(), []interface{}{1, 2, 3})
})
}

View File

@ -18,109 +18,120 @@ func getValue() interface{} {
}
func Test_Map_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.New()
m.Set("key1", "val1")
gtest.Assert(m.Keys(), []interface{}{"key1"})
t.Assert(m.Keys(), []interface{}{"key1"})
gtest.Assert(m.Get("key1"), "val1")
gtest.Assert(m.Size(), 1)
gtest.Assert(m.IsEmpty(), false)
t.Assert(m.Get("key1"), "val1")
t.Assert(m.Size(), 1)
t.Assert(m.IsEmpty(), false)
gtest.Assert(m.GetOrSet("key2", "val2"), "val2")
gtest.Assert(m.SetIfNotExist("key2", "val2"), false)
t.Assert(m.GetOrSet("key2", "val2"), "val2")
t.Assert(m.SetIfNotExist("key2", "val2"), false)
gtest.Assert(m.SetIfNotExist("key3", "val3"), true)
t.Assert(m.SetIfNotExist("key3", "val3"), true)
gtest.Assert(m.Remove("key2"), "val2")
gtest.Assert(m.Contains("key2"), false)
t.Assert(m.Remove("key2"), "val2")
t.Assert(m.Contains("key2"), false)
gtest.AssertIN("key3", m.Keys())
gtest.AssertIN("key1", m.Keys())
gtest.AssertIN("val3", m.Values())
gtest.AssertIN("val1", m.Values())
t.AssertIN("key3", m.Keys())
t.AssertIN("key1", m.Keys())
t.AssertIN("val3", m.Values())
t.AssertIN("val1", m.Values())
m.Flip()
gtest.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val1": "key1"})
t.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val1": "key1"})
m.Clear()
gtest.Assert(m.Size(), 0)
gtest.Assert(m.IsEmpty(), true)
t.Assert(m.Size(), 0)
t.Assert(m.IsEmpty(), true)
m2 := gmap.NewFrom(map[interface{}]interface{}{1: 1, "key1": "val1"})
gtest.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"})
t.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"})
})
}
func Test_Map_Set_Fun(t *testing.T) {
m := gmap.New()
m.GetOrSetFunc("fun", getValue)
m.GetOrSetFuncLock("funlock", getValue)
gtest.Assert(m.Get("funlock"), 3)
gtest.Assert(m.Get("fun"), 3)
m.GetOrSetFunc("fun", getValue)
gtest.Assert(m.SetIfNotExistFunc("fun", getValue), false)
gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false)
gtest.C(t, func(t *gtest.T) {
m := gmap.New()
m.GetOrSetFunc("fun", getValue)
m.GetOrSetFuncLock("funlock", getValue)
t.Assert(m.Get("funlock"), 3)
t.Assert(m.Get("fun"), 3)
m.GetOrSetFunc("fun", getValue)
t.Assert(m.SetIfNotExistFunc("fun", getValue), false)
t.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false)
})
}
func Test_Map_Batch(t *testing.T) {
m := gmap.New()
m.Sets(map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
gtest.Assert(m.Map(), map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
m.Removes([]interface{}{"key1", 1})
gtest.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"})
gtest.C(t, func(t *gtest.T) {
m := gmap.New()
m.Sets(map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
t.Assert(m.Map(), map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
m.Removes([]interface{}{"key1", 1})
t.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"})
})
}
func Test_Map_Iterator(t *testing.T) {
expect := map[interface{}]interface{}{1: 1, "key1": "val1"}
gtest.C(t, func(t *gtest.T) {
expect := map[interface{}]interface{}{1: 1, "key1": "val1"}
m := gmap.NewFrom(expect)
m.Iterator(func(k interface{}, v interface{}) bool {
gtest.Assert(expect[k], v)
return true
m := gmap.NewFrom(expect)
m.Iterator(func(k interface{}, v interface{}) bool {
t.Assert(expect[k], v)
return true
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k interface{}, v interface{}) bool {
i++
return true
})
m.Iterator(func(k interface{}, v interface{}) bool {
j++
return false
})
t.Assert(i, 2)
t.Assert(j, 1)
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k interface{}, v interface{}) bool {
i++
return true
})
m.Iterator(func(k interface{}, v interface{}) bool {
j++
return false
})
gtest.Assert(i, 2)
gtest.Assert(j, 1)
}
func Test_Map_Lock(t *testing.T) {
expect := map[interface{}]interface{}{1: 1, "key1": "val1"}
m := gmap.NewFrom(expect)
m.LockFunc(func(m map[interface{}]interface{}) {
gtest.Assert(m, expect)
})
m.RLockFunc(func(m map[interface{}]interface{}) {
gtest.Assert(m, expect)
gtest.C(t, func(t *gtest.T) {
expect := map[interface{}]interface{}{1: 1, "key1": "val1"}
m := gmap.NewFrom(expect)
m.LockFunc(func(m map[interface{}]interface{}) {
t.Assert(m, expect)
})
m.RLockFunc(func(m map[interface{}]interface{}) {
t.Assert(m, expect)
})
})
}
func Test_Map_Clone(t *testing.T) {
//clone 方法是深克隆
m := gmap.NewFrom(map[interface{}]interface{}{1: 1, "key1": "val1"})
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
gtest.AssertIN(1, m_clone.Keys())
gtest.C(t, func(t *gtest.T) {
//clone 方法是深克隆
m := gmap.NewFrom(map[interface{}]interface{}{1: 1, "key1": "val1"})
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
t.AssertIN(1, m_clone.Keys())
m_clone.Remove("key1")
//修改clone map,原 map 不影响
gtest.AssertIN("key1", m.Keys())
m_clone.Remove("key1")
//修改clone map,原 map 不影响
t.AssertIN("key1", m.Keys())
})
}
func Test_Map_Basic_Merge(t *testing.T) {
m1 := gmap.New()
m2 := gmap.New()
m1.Set("key1", "val1")
m2.Set("key2", "val2")
m1.Merge(m2)
gtest.Assert(m1.Map(), map[interface{}]interface{}{"key1": "val1", "key2": "val2"})
gtest.C(t, func(t *gtest.T) {
m1 := gmap.New()
m2 := gmap.New()
m1.Set("key1", "val1")
m2.Set("key2", "val2")
m1.Merge(m2)
t.Assert(m1.Map(), map[interface{}]interface{}{"key1": "val1", "key2": "val2"})
})
}

View File

@ -6,7 +6,7 @@ import (
"github.com/gogf/gf/container/gmap"
)
func Example_Normal_Basic() {
func Example_normalBasic() {
m := gmap.New()
//Add data
@ -61,7 +61,7 @@ func Example_Normal_Basic() {
fmt.Println(m.Size())
}
func Example_Normal_Merge() {
func Example_normalMerge() {
m1 := gmap.New()
m2 := gmap.New()
m1.Set("key1", "val1")

View File

@ -22,166 +22,181 @@ func anyAnyCallBack(int, interface{}) bool {
}
func Test_AnyAnyMap_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewAnyAnyMap()
m.Set(1, 1)
gtest.Assert(m.Get(1), 1)
gtest.Assert(m.Size(), 1)
gtest.Assert(m.IsEmpty(), false)
t.Assert(m.Get(1), 1)
t.Assert(m.Size(), 1)
t.Assert(m.IsEmpty(), false)
gtest.Assert(m.GetOrSet(2, "2"), "2")
gtest.Assert(m.SetIfNotExist(2, "2"), false)
t.Assert(m.GetOrSet(2, "2"), "2")
t.Assert(m.SetIfNotExist(2, "2"), false)
gtest.Assert(m.SetIfNotExist(3, 3), true)
t.Assert(m.SetIfNotExist(3, 3), true)
gtest.Assert(m.Remove(2), "2")
gtest.Assert(m.Contains(2), false)
t.Assert(m.Remove(2), "2")
t.Assert(m.Contains(2), false)
gtest.AssertIN(3, m.Keys())
gtest.AssertIN(1, m.Keys())
gtest.AssertIN(3, m.Values())
gtest.AssertIN(1, m.Values())
t.AssertIN(3, m.Keys())
t.AssertIN(1, m.Keys())
t.AssertIN(3, m.Values())
t.AssertIN(1, m.Values())
m.Flip()
gtest.Assert(m.Map(), map[interface{}]int{1: 1, 3: 3})
t.Assert(m.Map(), map[interface{}]int{1: 1, 3: 3})
m.Clear()
gtest.Assert(m.Size(), 0)
gtest.Assert(m.IsEmpty(), true)
t.Assert(m.Size(), 0)
t.Assert(m.IsEmpty(), true)
m2 := gmap.NewAnyAnyMapFrom(map[interface{}]interface{}{1: 1, 2: "2"})
gtest.Assert(m2.Map(), map[interface{}]interface{}{1: 1, 2: "2"})
t.Assert(m2.Map(), map[interface{}]interface{}{1: 1, 2: "2"})
})
}
func Test_AnyAnyMap_Set_Fun(t *testing.T) {
m := gmap.NewAnyAnyMap()
gtest.C(t, func(t *gtest.T) {
m := gmap.NewAnyAnyMap()
m.GetOrSetFunc(1, getAny)
m.GetOrSetFuncLock(2, getAny)
gtest.Assert(m.Get(1), 123)
gtest.Assert(m.Get(2), 123)
m.GetOrSetFunc(1, getAny)
m.GetOrSetFuncLock(2, getAny)
t.Assert(m.Get(1), 123)
t.Assert(m.Get(2), 123)
gtest.Assert(m.SetIfNotExistFunc(1, getAny), false)
gtest.Assert(m.SetIfNotExistFunc(3, getAny), true)
t.Assert(m.SetIfNotExistFunc(1, getAny), false)
t.Assert(m.SetIfNotExistFunc(3, getAny), true)
gtest.Assert(m.SetIfNotExistFuncLock(2, getAny), false)
gtest.Assert(m.SetIfNotExistFuncLock(4, getAny), true)
t.Assert(m.SetIfNotExistFuncLock(2, getAny), false)
t.Assert(m.SetIfNotExistFuncLock(4, getAny), true)
})
}
func Test_AnyAnyMap_Batch(t *testing.T) {
m := gmap.NewAnyAnyMap()
gtest.C(t, func(t *gtest.T) {
m := gmap.NewAnyAnyMap()
m.Sets(map[interface{}]interface{}{1: 1, 2: "2", 3: 3})
gtest.Assert(m.Map(), map[interface{}]interface{}{1: 1, 2: "2", 3: 3})
m.Removes([]interface{}{1, 2})
gtest.Assert(m.Map(), map[interface{}]interface{}{3: 3})
m.Sets(map[interface{}]interface{}{1: 1, 2: "2", 3: 3})
t.Assert(m.Map(), map[interface{}]interface{}{1: 1, 2: "2", 3: 3})
m.Removes([]interface{}{1, 2})
t.Assert(m.Map(), map[interface{}]interface{}{3: 3})
})
}
func Test_AnyAnyMap_Iterator(t *testing.T) {
expect := map[interface{}]interface{}{1: 1, 2: "2"}
m := gmap.NewAnyAnyMapFrom(expect)
m.Iterator(func(k interface{}, v interface{}) bool {
gtest.Assert(expect[k], v)
return true
gtest.C(t, func(t *gtest.T) {
expect := map[interface{}]interface{}{1: 1, 2: "2"}
m := gmap.NewAnyAnyMapFrom(expect)
m.Iterator(func(k interface{}, v interface{}) bool {
t.Assert(expect[k], v)
return true
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k interface{}, v interface{}) bool {
i++
return true
})
m.Iterator(func(k interface{}, v interface{}) bool {
j++
return false
})
t.Assert(i, "2")
t.Assert(j, 1)
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k interface{}, v interface{}) bool {
i++
return true
})
m.Iterator(func(k interface{}, v interface{}) bool {
j++
return false
})
gtest.Assert(i, "2")
gtest.Assert(j, 1)
}
func Test_AnyAnyMap_Lock(t *testing.T) {
expect := map[interface{}]interface{}{1: 1, 2: "2"}
m := gmap.NewAnyAnyMapFrom(expect)
m.LockFunc(func(m map[interface{}]interface{}) {
gtest.Assert(m, expect)
})
m.RLockFunc(func(m map[interface{}]interface{}) {
gtest.Assert(m, expect)
gtest.C(t, func(t *gtest.T) {
expect := map[interface{}]interface{}{1: 1, 2: "2"}
m := gmap.NewAnyAnyMapFrom(expect)
m.LockFunc(func(m map[interface{}]interface{}) {
t.Assert(m, expect)
})
m.RLockFunc(func(m map[interface{}]interface{}) {
t.Assert(m, expect)
})
})
}
func Test_AnyAnyMap_Clone(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
//clone 方法是深克隆
m := gmap.NewAnyAnyMapFrom(map[interface{}]interface{}{1: 1, 2: "2"})
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
gtest.AssertIN(1, m_clone.Keys())
t.AssertIN(1, m_clone.Keys())
m_clone.Remove(2)
//修改clone map,原 map 不影响
gtest.AssertIN(2, m.Keys())
t.AssertIN(2, m.Keys())
})
}
func Test_AnyAnyMap_Merge(t *testing.T) {
m1 := gmap.NewAnyAnyMap()
m2 := gmap.NewAnyAnyMap()
m1.Set(1, 1)
m2.Set(2, "2")
m1.Merge(m2)
gtest.Assert(m1.Map(), map[interface{}]interface{}{1: 1, 2: "2"})
gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewAnyAnyMap()
m2 := gmap.NewAnyAnyMap()
m1.Set(1, 1)
m2.Set(2, "2")
m1.Merge(m2)
t.Assert(m1.Map(), map[interface{}]interface{}{1: 1, 2: "2"})
})
}
func Test_AnyAnyMap_Map(t *testing.T) {
m := gmap.NewAnyAnyMap()
m.Set(1, 0)
m.Set(2, 2)
gtest.Assert(m.Get(1), 0)
gtest.Assert(m.Get(2), 2)
data := m.Map()
gtest.Assert(data[1], 0)
gtest.Assert(data[2], 2)
data[3] = 3
gtest.Assert(m.Get(3), 3)
m.Set(4, 4)
gtest.Assert(data[4], 4)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewAnyAnyMap()
m.Set(1, 0)
m.Set(2, 2)
t.Assert(m.Get(1), 0)
t.Assert(m.Get(2), 2)
data := m.Map()
t.Assert(data[1], 0)
t.Assert(data[2], 2)
data[3] = 3
t.Assert(m.Get(3), 3)
m.Set(4, 4)
t.Assert(data[4], 4)
})
}
func Test_AnyAnyMap_MapCopy(t *testing.T) {
m := gmap.NewAnyAnyMap()
m.Set(1, 0)
m.Set(2, 2)
gtest.Assert(m.Get(1), 0)
gtest.Assert(m.Get(2), 2)
data := m.MapCopy()
gtest.Assert(data[1], 0)
gtest.Assert(data[2], 2)
data[3] = 3
gtest.Assert(m.Get(3), nil)
m.Set(4, 4)
gtest.Assert(data[4], nil)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewAnyAnyMap()
m.Set(1, 0)
m.Set(2, 2)
t.Assert(m.Get(1), 0)
t.Assert(m.Get(2), 2)
data := m.MapCopy()
t.Assert(data[1], 0)
t.Assert(data[2], 2)
data[3] = 3
t.Assert(m.Get(3), nil)
m.Set(4, 4)
t.Assert(data[4], nil)
})
}
func Test_AnyAnyMap_FilterEmpty(t *testing.T) {
m := gmap.NewAnyAnyMap()
m.Set(1, 0)
m.Set(2, 2)
gtest.Assert(m.Get(1), 0)
gtest.Assert(m.Get(2), 2)
m.FilterEmpty()
gtest.Assert(m.Get(1), nil)
gtest.Assert(m.Get(2), 2)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewAnyAnyMap()
m.Set(1, 0)
m.Set(2, 2)
t.Assert(m.Get(1), 0)
t.Assert(m.Get(2), 2)
m.FilterEmpty()
t.Assert(m.Get(1), nil)
t.Assert(m.Get(2), 2)
})
}
func Test_AnyAnyMap_Json(t *testing.T) {
// Marshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapAnyAny{
"k1": "v1",
"k2": "v2",
@ -189,125 +204,125 @@ func Test_AnyAnyMap_Json(t *testing.T) {
m1 := gmap.NewAnyAnyMapFrom(data)
b1, err1 := json.Marshal(m1)
b2, err2 := json.Marshal(gconv.Map(data))
gtest.Assert(err1, err2)
gtest.Assert(b1, b2)
t.Assert(err1, err2)
t.Assert(b1, b2)
})
// Unmarshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapAnyAny{
"k1": "v1",
"k2": "v2",
}
b, err := json.Marshal(gconv.Map(data))
gtest.Assert(err, nil)
t.Assert(err, nil)
m := gmap.New()
err = json.Unmarshal(b, m)
gtest.Assert(err, nil)
gtest.Assert(m.Get("k1"), data["k1"])
gtest.Assert(m.Get("k2"), data["k2"])
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapAnyAny{
"k1": "v1",
"k2": "v2",
}
b, err := json.Marshal(gconv.Map(data))
gtest.Assert(err, nil)
t.Assert(err, nil)
var m gmap.Map
err = json.Unmarshal(b, &m)
gtest.Assert(err, nil)
gtest.Assert(m.Get("k1"), data["k1"])
gtest.Assert(m.Get("k2"), data["k2"])
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
})
}
func Test_AnyAnyMap_Pop(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewAnyAnyMapFrom(g.MapAnyAny{
"k1": "v1",
"k2": "v2",
})
gtest.Assert(m.Size(), 2)
t.Assert(m.Size(), 2)
k1, v1 := m.Pop()
gtest.AssertIN(k1, g.Slice{"k1", "k2"})
gtest.AssertIN(v1, g.Slice{"v1", "v2"})
gtest.Assert(m.Size(), 1)
t.AssertIN(k1, g.Slice{"k1", "k2"})
t.AssertIN(v1, g.Slice{"v1", "v2"})
t.Assert(m.Size(), 1)
k2, v2 := m.Pop()
gtest.AssertIN(k2, g.Slice{"k1", "k2"})
gtest.AssertIN(v2, g.Slice{"v1", "v2"})
gtest.Assert(m.Size(), 0)
t.AssertIN(k2, g.Slice{"k1", "k2"})
t.AssertIN(v2, g.Slice{"v1", "v2"})
t.Assert(m.Size(), 0)
gtest.AssertNE(k1, k2)
gtest.AssertNE(v1, v2)
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
})
}
func Test_AnyAnyMap_Pops(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewAnyAnyMapFrom(g.MapAnyAny{
"k1": "v1",
"k2": "v2",
"k3": "v3",
})
gtest.Assert(m.Size(), 3)
t.Assert(m.Size(), 3)
kArray := garray.New()
vArray := garray.New()
for k, v := range m.Pops(1) {
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
t.AssertIN(k, g.Slice{"k1", "k2", "k3"})
t.AssertIN(v, g.Slice{"v1", "v2", "v3"})
kArray.Append(k)
vArray.Append(v)
}
gtest.Assert(m.Size(), 2)
t.Assert(m.Size(), 2)
for k, v := range m.Pops(2) {
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
t.AssertIN(k, g.Slice{"k1", "k2", "k3"})
t.AssertIN(v, g.Slice{"v1", "v2", "v3"})
kArray.Append(k)
vArray.Append(v)
}
gtest.Assert(m.Size(), 0)
t.Assert(m.Size(), 0)
gtest.Assert(kArray.Unique().Len(), 3)
gtest.Assert(vArray.Unique().Len(), 3)
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
})
}
func TestAnyAnyMap_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Map *gmap.Map
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"k1":"v1","k2":"v2"}`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get("k1"), "v1")
gtest.Assert(t.Map.Get("k2"), "v2")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get("k1"), "v1")
t.Assert(v.Map.Get("k2"), "v2")
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.Map{
"k1": "v1",
"k2": "v2",
},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get("k1"), "v1")
gtest.Assert(t.Map.Get("k2"), "v2")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get("k1"), "v1")
t.Assert(v.Map.Get("k2"), "v2")
})
}

View File

@ -24,161 +24,178 @@ func intAnyCallBack(int, interface{}) bool {
return true
}
func Test_IntAnyMap_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntAnyMap()
m.Set(1, 1)
gtest.Assert(m.Get(1), 1)
gtest.Assert(m.Size(), 1)
gtest.Assert(m.IsEmpty(), false)
t.Assert(m.Get(1), 1)
t.Assert(m.Size(), 1)
t.Assert(m.IsEmpty(), false)
gtest.Assert(m.GetOrSet(2, "2"), "2")
gtest.Assert(m.SetIfNotExist(2, "2"), false)
t.Assert(m.GetOrSet(2, "2"), "2")
t.Assert(m.SetIfNotExist(2, "2"), false)
gtest.Assert(m.SetIfNotExist(3, 3), true)
t.Assert(m.SetIfNotExist(3, 3), true)
gtest.Assert(m.Remove(2), "2")
gtest.Assert(m.Contains(2), false)
t.Assert(m.Remove(2), "2")
t.Assert(m.Contains(2), false)
gtest.AssertIN(3, m.Keys())
gtest.AssertIN(1, m.Keys())
gtest.AssertIN(3, m.Values())
gtest.AssertIN(1, m.Values())
t.AssertIN(3, m.Keys())
t.AssertIN(1, m.Keys())
t.AssertIN(3, m.Values())
t.AssertIN(1, m.Values())
m.Flip()
gtest.Assert(m.Map(), map[interface{}]int{1: 1, 3: 3})
t.Assert(m.Map(), map[interface{}]int{1: 1, 3: 3})
m.Clear()
gtest.Assert(m.Size(), 0)
gtest.Assert(m.IsEmpty(), true)
t.Assert(m.Size(), 0)
t.Assert(m.IsEmpty(), true)
m2 := gmap.NewIntAnyMapFrom(map[int]interface{}{1: 1, 2: "2"})
gtest.Assert(m2.Map(), map[int]interface{}{1: 1, 2: "2"})
t.Assert(m2.Map(), map[int]interface{}{1: 1, 2: "2"})
})
}
func Test_IntAnyMap_Set_Fun(t *testing.T) {
m := gmap.NewIntAnyMap()
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntAnyMap()
m.GetOrSetFunc(1, getAny)
m.GetOrSetFuncLock(2, getAny)
gtest.Assert(m.Get(1), 123)
gtest.Assert(m.Get(2), 123)
m.GetOrSetFunc(1, getAny)
m.GetOrSetFuncLock(2, getAny)
t.Assert(m.Get(1), 123)
t.Assert(m.Get(2), 123)
gtest.Assert(m.SetIfNotExistFunc(1, getAny), false)
gtest.Assert(m.SetIfNotExistFunc(3, getAny), true)
gtest.Assert(m.SetIfNotExistFuncLock(2, getAny), false)
gtest.Assert(m.SetIfNotExistFuncLock(4, getAny), true)
t.Assert(m.SetIfNotExistFunc(1, getAny), false)
t.Assert(m.SetIfNotExistFunc(3, getAny), true)
t.Assert(m.SetIfNotExistFuncLock(2, getAny), false)
t.Assert(m.SetIfNotExistFuncLock(4, getAny), true)
})
}
func Test_IntAnyMap_Batch(t *testing.T) {
m := gmap.NewIntAnyMap()
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntAnyMap()
m.Sets(map[int]interface{}{1: 1, 2: "2", 3: 3})
gtest.Assert(m.Map(), map[int]interface{}{1: 1, 2: "2", 3: 3})
m.Removes([]int{1, 2})
gtest.Assert(m.Map(), map[int]interface{}{3: 3})
m.Sets(map[int]interface{}{1: 1, 2: "2", 3: 3})
t.Assert(m.Map(), map[int]interface{}{1: 1, 2: "2", 3: 3})
m.Removes([]int{1, 2})
t.Assert(m.Map(), map[int]interface{}{3: 3})
})
}
func Test_IntAnyMap_Iterator(t *testing.T) {
expect := map[int]interface{}{1: 1, 2: "2"}
m := gmap.NewIntAnyMapFrom(expect)
m.Iterator(func(k int, v interface{}) bool {
gtest.Assert(expect[k], v)
return true
gtest.C(t, func(t *gtest.T) {
expect := map[int]interface{}{1: 1, 2: "2"}
m := gmap.NewIntAnyMapFrom(expect)
m.Iterator(func(k int, v interface{}) bool {
t.Assert(expect[k], v)
return true
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k int, v interface{}) bool {
i++
return true
})
m.Iterator(func(k int, v interface{}) bool {
j++
return false
})
t.Assert(i, "2")
t.Assert(j, 1)
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k int, v interface{}) bool {
i++
return true
})
m.Iterator(func(k int, v interface{}) bool {
j++
return false
})
gtest.Assert(i, "2")
gtest.Assert(j, 1)
}
func Test_IntAnyMap_Lock(t *testing.T) {
expect := map[int]interface{}{1: 1, 2: "2"}
m := gmap.NewIntAnyMapFrom(expect)
m.LockFunc(func(m map[int]interface{}) {
gtest.Assert(m, expect)
})
m.RLockFunc(func(m map[int]interface{}) {
gtest.Assert(m, expect)
gtest.C(t, func(t *gtest.T) {
expect := map[int]interface{}{1: 1, 2: "2"}
m := gmap.NewIntAnyMapFrom(expect)
m.LockFunc(func(m map[int]interface{}) {
t.Assert(m, expect)
})
m.RLockFunc(func(m map[int]interface{}) {
t.Assert(m, expect)
})
})
}
func Test_IntAnyMap_Clone(t *testing.T) {
//clone 方法是深克隆
m := gmap.NewIntAnyMapFrom(map[int]interface{}{1: 1, 2: "2"})
gtest.C(t, func(t *gtest.T) {
//clone 方法是深克隆
m := gmap.NewIntAnyMapFrom(map[int]interface{}{1: 1, 2: "2"})
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
gtest.AssertIN(1, m_clone.Keys())
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
t.AssertIN(1, m_clone.Keys())
m_clone.Remove(2)
//修改clone map,原 map 不影响
gtest.AssertIN(2, m.Keys())
m_clone.Remove(2)
//修改clone map,原 map 不影响
t.AssertIN(2, m.Keys())
})
}
func Test_IntAnyMap_Merge(t *testing.T) {
m1 := gmap.NewIntAnyMap()
m2 := gmap.NewIntAnyMap()
m1.Set(1, 1)
m2.Set(2, "2")
m1.Merge(m2)
gtest.Assert(m1.Map(), map[int]interface{}{1: 1, 2: "2"})
gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewIntAnyMap()
m2 := gmap.NewIntAnyMap()
m1.Set(1, 1)
m2.Set(2, "2")
m1.Merge(m2)
t.Assert(m1.Map(), map[int]interface{}{1: 1, 2: "2"})
})
}
func Test_IntAnyMap_Map(t *testing.T) {
m := gmap.NewIntAnyMap()
m.Set(1, 0)
m.Set(2, 2)
gtest.Assert(m.Get(1), 0)
gtest.Assert(m.Get(2), 2)
data := m.Map()
gtest.Assert(data[1], 0)
gtest.Assert(data[2], 2)
data[3] = 3
gtest.Assert(m.Get(3), 3)
m.Set(4, 4)
gtest.Assert(data[4], 4)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntAnyMap()
m.Set(1, 0)
m.Set(2, 2)
t.Assert(m.Get(1), 0)
t.Assert(m.Get(2), 2)
data := m.Map()
t.Assert(data[1], 0)
t.Assert(data[2], 2)
data[3] = 3
t.Assert(m.Get(3), 3)
m.Set(4, 4)
t.Assert(data[4], 4)
})
}
func Test_IntAnyMap_MapCopy(t *testing.T) {
m := gmap.NewIntAnyMap()
m.Set(1, 0)
m.Set(2, 2)
gtest.Assert(m.Get(1), 0)
gtest.Assert(m.Get(2), 2)
data := m.MapCopy()
gtest.Assert(data[1], 0)
gtest.Assert(data[2], 2)
data[3] = 3
gtest.Assert(m.Get(3), nil)
m.Set(4, 4)
gtest.Assert(data[4], nil)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntAnyMap()
m.Set(1, 0)
m.Set(2, 2)
t.Assert(m.Get(1), 0)
t.Assert(m.Get(2), 2)
data := m.MapCopy()
t.Assert(data[1], 0)
t.Assert(data[2], 2)
data[3] = 3
t.Assert(m.Get(3), nil)
m.Set(4, 4)
t.Assert(data[4], nil)
})
}
func Test_IntAnyMap_FilterEmpty(t *testing.T) {
m := gmap.NewIntAnyMap()
m.Set(1, 0)
m.Set(2, 2)
gtest.Assert(m.Size(), 2)
gtest.Assert(m.Get(1), 0)
gtest.Assert(m.Get(2), 2)
m.FilterEmpty()
gtest.Assert(m.Size(), 1)
gtest.Assert(m.Get(2), 2)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntAnyMap()
m.Set(1, 0)
m.Set(2, 2)
t.Assert(m.Size(), 2)
t.Assert(m.Get(1), 0)
t.Assert(m.Get(2), 2)
m.FilterEmpty()
t.Assert(m.Size(), 1)
t.Assert(m.Get(2), 2)
})
}
func Test_IntAnyMap_Json(t *testing.T) {
// Marshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapIntAny{
1: "v1",
2: "v2",
@ -186,111 +203,111 @@ func Test_IntAnyMap_Json(t *testing.T) {
m1 := gmap.NewIntAnyMapFrom(data)
b1, err1 := json.Marshal(m1)
b2, err2 := json.Marshal(data)
gtest.Assert(err1, err2)
gtest.Assert(b1, b2)
t.Assert(err1, err2)
t.Assert(b1, b2)
})
// Unmarshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapIntAny{
1: "v1",
2: "v2",
}
b, err := json.Marshal(data)
gtest.Assert(err, nil)
t.Assert(err, nil)
m := gmap.NewIntAnyMap()
err = json.Unmarshal(b, m)
gtest.Assert(err, nil)
gtest.Assert(m.Get(1), data[1])
gtest.Assert(m.Get(2), data[2])
t.Assert(err, nil)
t.Assert(m.Get(1), data[1])
t.Assert(m.Get(2), data[2])
})
}
func Test_IntAnyMap_Pop(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntAnyMapFrom(g.MapIntAny{
1: "v1",
2: "v2",
})
gtest.Assert(m.Size(), 2)
t.Assert(m.Size(), 2)
k1, v1 := m.Pop()
gtest.AssertIN(k1, g.Slice{1, 2})
gtest.AssertIN(v1, g.Slice{"v1", "v2"})
gtest.Assert(m.Size(), 1)
t.AssertIN(k1, g.Slice{1, 2})
t.AssertIN(v1, g.Slice{"v1", "v2"})
t.Assert(m.Size(), 1)
k2, v2 := m.Pop()
gtest.AssertIN(k2, g.Slice{1, 2})
gtest.AssertIN(v2, g.Slice{"v1", "v2"})
gtest.Assert(m.Size(), 0)
t.AssertIN(k2, g.Slice{1, 2})
t.AssertIN(v2, g.Slice{"v1", "v2"})
t.Assert(m.Size(), 0)
gtest.AssertNE(k1, k2)
gtest.AssertNE(v1, v2)
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
})
}
func Test_IntAnyMap_Pops(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntAnyMapFrom(g.MapIntAny{
1: "v1",
2: "v2",
3: "v3",
})
gtest.Assert(m.Size(), 3)
t.Assert(m.Size(), 3)
kArray := garray.New()
vArray := garray.New()
for k, v := range m.Pops(1) {
gtest.AssertIN(k, g.Slice{1, 2, 3})
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
t.AssertIN(k, g.Slice{1, 2, 3})
t.AssertIN(v, g.Slice{"v1", "v2", "v3"})
kArray.Append(k)
vArray.Append(v)
}
gtest.Assert(m.Size(), 2)
t.Assert(m.Size(), 2)
for k, v := range m.Pops(2) {
gtest.AssertIN(k, g.Slice{1, 2, 3})
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
t.AssertIN(k, g.Slice{1, 2, 3})
t.AssertIN(v, g.Slice{"v1", "v2", "v3"})
kArray.Append(k)
vArray.Append(v)
}
gtest.Assert(m.Size(), 0)
t.Assert(m.Size(), 0)
gtest.Assert(kArray.Unique().Len(), 3)
gtest.Assert(vArray.Unique().Len(), 3)
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
})
}
func TestIntAnyMap_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Map *gmap.IntAnyMap
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"1":"v1","2":"v2"}`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get(1), "v1")
gtest.Assert(t.Map.Get(2), "v2")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get(1), "v1")
t.Assert(v.Map.Get(2), "v2")
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.MapIntAny{
1: "v1",
2: "v2",
},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get(1), "v1")
gtest.Assert(t.Map.Get(2), "v2")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get(1), "v1")
t.Assert(v.Map.Get(2), "v2")
})
}

View File

@ -24,164 +24,180 @@ func intIntCallBack(int, int) bool {
return true
}
func Test_IntIntMap_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntIntMap()
m.Set(1, 1)
gtest.Assert(m.Get(1), 1)
gtest.Assert(m.Size(), 1)
gtest.Assert(m.IsEmpty(), false)
t.Assert(m.Get(1), 1)
t.Assert(m.Size(), 1)
t.Assert(m.IsEmpty(), false)
gtest.Assert(m.GetOrSet(2, 2), 2)
gtest.Assert(m.SetIfNotExist(2, 2), false)
t.Assert(m.GetOrSet(2, 2), 2)
t.Assert(m.SetIfNotExist(2, 2), false)
gtest.Assert(m.SetIfNotExist(3, 3), true)
t.Assert(m.SetIfNotExist(3, 3), true)
gtest.Assert(m.Remove(2), 2)
gtest.Assert(m.Contains(2), false)
t.Assert(m.Remove(2), 2)
t.Assert(m.Contains(2), false)
gtest.AssertIN(3, m.Keys())
gtest.AssertIN(1, m.Keys())
gtest.AssertIN(3, m.Values())
gtest.AssertIN(1, m.Values())
t.AssertIN(3, m.Keys())
t.AssertIN(1, m.Keys())
t.AssertIN(3, m.Values())
t.AssertIN(1, m.Values())
m.Flip()
gtest.Assert(m.Map(), map[int]int{1: 1, 3: 3})
t.Assert(m.Map(), map[int]int{1: 1, 3: 3})
m.Clear()
gtest.Assert(m.Size(), 0)
gtest.Assert(m.IsEmpty(), true)
t.Assert(m.Size(), 0)
t.Assert(m.IsEmpty(), true)
m2 := gmap.NewIntIntMapFrom(map[int]int{1: 1, 2: 2})
gtest.Assert(m2.Map(), map[int]int{1: 1, 2: 2})
t.Assert(m2.Map(), map[int]int{1: 1, 2: 2})
})
}
func Test_IntIntMap_Set_Fun(t *testing.T) {
m := gmap.NewIntIntMap()
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntIntMap()
m.GetOrSetFunc(1, getInt)
m.GetOrSetFuncLock(2, getInt)
gtest.Assert(m.Get(1), 123)
gtest.Assert(m.Get(2), 123)
gtest.Assert(m.SetIfNotExistFunc(1, getInt), false)
gtest.Assert(m.SetIfNotExistFunc(3, getInt), true)
gtest.Assert(m.SetIfNotExistFuncLock(2, getInt), false)
gtest.Assert(m.SetIfNotExistFuncLock(4, getInt), true)
m.GetOrSetFunc(1, getInt)
m.GetOrSetFuncLock(2, getInt)
t.Assert(m.Get(1), 123)
t.Assert(m.Get(2), 123)
t.Assert(m.SetIfNotExistFunc(1, getInt), false)
t.Assert(m.SetIfNotExistFunc(3, getInt), true)
t.Assert(m.SetIfNotExistFuncLock(2, getInt), false)
t.Assert(m.SetIfNotExistFuncLock(4, getInt), true)
})
}
func Test_IntIntMap_Batch(t *testing.T) {
m := gmap.NewIntIntMap()
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntIntMap()
m.Sets(map[int]int{1: 1, 2: 2, 3: 3})
m.Iterator(intIntCallBack)
gtest.Assert(m.Map(), map[int]int{1: 1, 2: 2, 3: 3})
m.Removes([]int{1, 2})
gtest.Assert(m.Map(), map[int]int{3: 3})
m.Sets(map[int]int{1: 1, 2: 2, 3: 3})
m.Iterator(intIntCallBack)
t.Assert(m.Map(), map[int]int{1: 1, 2: 2, 3: 3})
m.Removes([]int{1, 2})
t.Assert(m.Map(), map[int]int{3: 3})
})
}
func Test_IntIntMap_Iterator(t *testing.T) {
expect := map[int]int{1: 1, 2: 2}
m := gmap.NewIntIntMapFrom(expect)
m.Iterator(func(k int, v int) bool {
gtest.Assert(expect[k], v)
return true
gtest.C(t, func(t *gtest.T) {
expect := map[int]int{1: 1, 2: 2}
m := gmap.NewIntIntMapFrom(expect)
m.Iterator(func(k int, v int) bool {
t.Assert(expect[k], v)
return true
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k int, v int) bool {
i++
return true
})
m.Iterator(func(k int, v int) bool {
j++
return false
})
t.Assert(i, 2)
t.Assert(j, 1)
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k int, v int) bool {
i++
return true
})
m.Iterator(func(k int, v int) bool {
j++
return false
})
gtest.Assert(i, 2)
gtest.Assert(j, 1)
}
func Test_IntIntMap_Lock(t *testing.T) {
expect := map[int]int{1: 1, 2: 2}
m := gmap.NewIntIntMapFrom(expect)
m.LockFunc(func(m map[int]int) {
gtest.Assert(m, expect)
gtest.C(t, func(t *gtest.T) {
expect := map[int]int{1: 1, 2: 2}
m := gmap.NewIntIntMapFrom(expect)
m.LockFunc(func(m map[int]int) {
t.Assert(m, expect)
})
m.RLockFunc(func(m map[int]int) {
t.Assert(m, expect)
})
})
m.RLockFunc(func(m map[int]int) {
gtest.Assert(m, expect)
})
}
func Test_IntIntMap_Clone(t *testing.T) {
//clone 方法是深克隆
m := gmap.NewIntIntMapFrom(map[int]int{1: 1, 2: 2})
gtest.C(t, func(t *gtest.T) {
//clone 方法是深克隆
m := gmap.NewIntIntMapFrom(map[int]int{1: 1, 2: 2})
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
gtest.AssertIN(1, m_clone.Keys())
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
t.AssertIN(1, m_clone.Keys())
m_clone.Remove(2)
//修改clone map,原 map 不影响
gtest.AssertIN(2, m.Keys())
m_clone.Remove(2)
//修改clone map,原 map 不影响
t.AssertIN(2, m.Keys())
})
}
func Test_IntIntMap_Merge(t *testing.T) {
m1 := gmap.NewIntIntMap()
m2 := gmap.NewIntIntMap()
m1.Set(1, 1)
m2.Set(2, 2)
m1.Merge(m2)
gtest.Assert(m1.Map(), map[int]int{1: 1, 2: 2})
gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewIntIntMap()
m2 := gmap.NewIntIntMap()
m1.Set(1, 1)
m2.Set(2, 2)
m1.Merge(m2)
t.Assert(m1.Map(), map[int]int{1: 1, 2: 2})
})
}
func Test_IntIntMap_Map(t *testing.T) {
m := gmap.NewIntIntMap()
m.Set(1, 0)
m.Set(2, 2)
gtest.Assert(m.Get(1), 0)
gtest.Assert(m.Get(2), 2)
data := m.Map()
gtest.Assert(data[1], 0)
gtest.Assert(data[2], 2)
data[3] = 3
gtest.Assert(m.Get(3), 3)
m.Set(4, 4)
gtest.Assert(data[4], 4)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntIntMap()
m.Set(1, 0)
m.Set(2, 2)
t.Assert(m.Get(1), 0)
t.Assert(m.Get(2), 2)
data := m.Map()
t.Assert(data[1], 0)
t.Assert(data[2], 2)
data[3] = 3
t.Assert(m.Get(3), 3)
m.Set(4, 4)
t.Assert(data[4], 4)
})
}
func Test_IntIntMap_MapCopy(t *testing.T) {
m := gmap.NewIntIntMap()
m.Set(1, 0)
m.Set(2, 2)
gtest.Assert(m.Get(1), 0)
gtest.Assert(m.Get(2), 2)
data := m.MapCopy()
gtest.Assert(data[1], 0)
gtest.Assert(data[2], 2)
data[3] = 3
gtest.Assert(m.Get(3), 0)
m.Set(4, 4)
gtest.Assert(data[4], 0)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntIntMap()
m.Set(1, 0)
m.Set(2, 2)
t.Assert(m.Get(1), 0)
t.Assert(m.Get(2), 2)
data := m.MapCopy()
t.Assert(data[1], 0)
t.Assert(data[2], 2)
data[3] = 3
t.Assert(m.Get(3), 0)
m.Set(4, 4)
t.Assert(data[4], 0)
})
}
func Test_IntIntMap_FilterEmpty(t *testing.T) {
m := gmap.NewIntIntMap()
m.Set(1, 0)
m.Set(2, 2)
gtest.Assert(m.Size(), 2)
gtest.Assert(m.Get(1), 0)
gtest.Assert(m.Get(2), 2)
m.FilterEmpty()
gtest.Assert(m.Size(), 1)
gtest.Assert(m.Get(2), 2)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntIntMap()
m.Set(1, 0)
m.Set(2, 2)
t.Assert(m.Size(), 2)
t.Assert(m.Get(1), 0)
t.Assert(m.Get(2), 2)
m.FilterEmpty()
t.Assert(m.Size(), 1)
t.Assert(m.Get(2), 2)
})
}
func Test_IntIntMap_Json(t *testing.T) {
// Marshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapIntInt{
1: 10,
2: 20,
@ -189,111 +205,111 @@ func Test_IntIntMap_Json(t *testing.T) {
m1 := gmap.NewIntIntMapFrom(data)
b1, err1 := json.Marshal(m1)
b2, err2 := json.Marshal(data)
gtest.Assert(err1, err2)
gtest.Assert(b1, b2)
t.Assert(err1, err2)
t.Assert(b1, b2)
})
// Unmarshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapIntInt{
1: 10,
2: 20,
}
b, err := json.Marshal(data)
gtest.Assert(err, nil)
t.Assert(err, nil)
m := gmap.NewIntIntMap()
err = json.Unmarshal(b, m)
gtest.Assert(err, nil)
gtest.Assert(m.Get(1), data[1])
gtest.Assert(m.Get(2), data[2])
t.Assert(err, nil)
t.Assert(m.Get(1), data[1])
t.Assert(m.Get(2), data[2])
})
}
func Test_IntIntMap_Pop(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntIntMapFrom(g.MapIntInt{
1: 11,
2: 22,
})
gtest.Assert(m.Size(), 2)
t.Assert(m.Size(), 2)
k1, v1 := m.Pop()
gtest.AssertIN(k1, g.Slice{1, 2})
gtest.AssertIN(v1, g.Slice{11, 22})
gtest.Assert(m.Size(), 1)
t.AssertIN(k1, g.Slice{1, 2})
t.AssertIN(v1, g.Slice{11, 22})
t.Assert(m.Size(), 1)
k2, v2 := m.Pop()
gtest.AssertIN(k2, g.Slice{1, 2})
gtest.AssertIN(v2, g.Slice{11, 22})
gtest.Assert(m.Size(), 0)
t.AssertIN(k2, g.Slice{1, 2})
t.AssertIN(v2, g.Slice{11, 22})
t.Assert(m.Size(), 0)
gtest.AssertNE(k1, k2)
gtest.AssertNE(v1, v2)
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
})
}
func Test_IntIntMap_Pops(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntIntMapFrom(g.MapIntInt{
1: 11,
2: 22,
3: 33,
})
gtest.Assert(m.Size(), 3)
t.Assert(m.Size(), 3)
kArray := garray.New()
vArray := garray.New()
for k, v := range m.Pops(1) {
gtest.AssertIN(k, g.Slice{1, 2, 3})
gtest.AssertIN(v, g.Slice{11, 22, 33})
t.AssertIN(k, g.Slice{1, 2, 3})
t.AssertIN(v, g.Slice{11, 22, 33})
kArray.Append(k)
vArray.Append(v)
}
gtest.Assert(m.Size(), 2)
t.Assert(m.Size(), 2)
for k, v := range m.Pops(2) {
gtest.AssertIN(k, g.Slice{1, 2, 3})
gtest.AssertIN(v, g.Slice{11, 22, 33})
t.AssertIN(k, g.Slice{1, 2, 3})
t.AssertIN(v, g.Slice{11, 22, 33})
kArray.Append(k)
vArray.Append(v)
}
gtest.Assert(m.Size(), 0)
t.Assert(m.Size(), 0)
gtest.Assert(kArray.Unique().Len(), 3)
gtest.Assert(vArray.Unique().Len(), 3)
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
})
}
func TestIntIntMap_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Map *gmap.IntIntMap
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"1":1,"2":2}`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get(1), "1")
gtest.Assert(t.Map.Get(2), "2")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get(1), "1")
t.Assert(v.Map.Get(2), "2")
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.MapIntAny{
1: 1,
2: 2,
},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get(1), "1")
gtest.Assert(t.Map.Get(2), "2")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get(1), "1")
t.Assert(v.Map.Get(2), "2")
})
}

View File

@ -24,165 +24,179 @@ func intStrCallBack(int, string) bool {
return true
}
func Test_IntStrMap_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMap()
m.Set(1, "a")
gtest.Assert(m.Get(1), "a")
gtest.Assert(m.Size(), 1)
gtest.Assert(m.IsEmpty(), false)
t.Assert(m.Get(1), "a")
t.Assert(m.Size(), 1)
t.Assert(m.IsEmpty(), false)
gtest.Assert(m.GetOrSet(2, "b"), "b")
gtest.Assert(m.SetIfNotExist(2, "b"), false)
t.Assert(m.GetOrSet(2, "b"), "b")
t.Assert(m.SetIfNotExist(2, "b"), false)
gtest.Assert(m.SetIfNotExist(3, "c"), true)
t.Assert(m.SetIfNotExist(3, "c"), true)
gtest.Assert(m.Remove(2), "b")
gtest.Assert(m.Contains(2), false)
t.Assert(m.Remove(2), "b")
t.Assert(m.Contains(2), false)
gtest.AssertIN(3, m.Keys())
gtest.AssertIN(1, m.Keys())
gtest.AssertIN("a", m.Values())
gtest.AssertIN("c", m.Values())
t.AssertIN(3, m.Keys())
t.AssertIN(1, m.Keys())
t.AssertIN("a", m.Values())
t.AssertIN("c", m.Values())
//反转之后不成为以下 map,flip 操作只是翻转原 map
//gtest.Assert(m.Map(), map[string]int{"a": 1, "c": 3})
//t.Assert(m.Map(), map[string]int{"a": 1, "c": 3})
m_f := gmap.NewIntStrMap()
m_f.Set(1, "2")
m_f.Flip()
gtest.Assert(m_f.Map(), map[int]string{2: "1"})
t.Assert(m_f.Map(), map[int]string{2: "1"})
m.Clear()
gtest.Assert(m.Size(), 0)
gtest.Assert(m.IsEmpty(), true)
t.Assert(m.Size(), 0)
t.Assert(m.IsEmpty(), true)
m2 := gmap.NewIntStrMapFrom(map[int]string{1: "a", 2: "b"})
gtest.Assert(m2.Map(), map[int]string{1: "a", 2: "b"})
t.Assert(m2.Map(), map[int]string{1: "a", 2: "b"})
})
}
func Test_IntStrMap_Set_Fun(t *testing.T) {
m := gmap.NewIntStrMap()
m.GetOrSetFunc(1, getStr)
m.GetOrSetFuncLock(2, getStr)
gtest.Assert(m.Get(1), "z")
gtest.Assert(m.Get(2), "z")
gtest.Assert(m.SetIfNotExistFunc(1, getStr), false)
gtest.Assert(m.SetIfNotExistFunc(3, getStr), true)
gtest.Assert(m.SetIfNotExistFuncLock(2, getStr), false)
gtest.Assert(m.SetIfNotExistFuncLock(4, getStr), true)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMap()
m.GetOrSetFunc(1, getStr)
m.GetOrSetFuncLock(2, getStr)
t.Assert(m.Get(1), "z")
t.Assert(m.Get(2), "z")
t.Assert(m.SetIfNotExistFunc(1, getStr), false)
t.Assert(m.SetIfNotExistFunc(3, getStr), true)
t.Assert(m.SetIfNotExistFuncLock(2, getStr), false)
t.Assert(m.SetIfNotExistFuncLock(4, getStr), true)
})
}
func Test_IntStrMap_Batch(t *testing.T) {
m := gmap.NewIntStrMap()
m.Sets(map[int]string{1: "a", 2: "b", 3: "c"})
gtest.Assert(m.Map(), map[int]string{1: "a", 2: "b", 3: "c"})
m.Removes([]int{1, 2})
gtest.Assert(m.Map(), map[int]interface{}{3: "c"})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMap()
m.Sets(map[int]string{1: "a", 2: "b", 3: "c"})
t.Assert(m.Map(), map[int]string{1: "a", 2: "b", 3: "c"})
m.Removes([]int{1, 2})
t.Assert(m.Map(), map[int]interface{}{3: "c"})
})
}
func Test_IntStrMap_Iterator(t *testing.T) {
expect := map[int]string{1: "a", 2: "b"}
m := gmap.NewIntStrMapFrom(expect)
m.Iterator(func(k int, v string) bool {
gtest.Assert(expect[k], v)
return true
gtest.C(t, func(t *gtest.T) {
expect := map[int]string{1: "a", 2: "b"}
m := gmap.NewIntStrMapFrom(expect)
m.Iterator(func(k int, v string) bool {
t.Assert(expect[k], v)
return true
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k int, v string) bool {
i++
return true
})
m.Iterator(func(k int, v string) bool {
j++
return false
})
t.Assert(i, 2)
t.Assert(j, 1)
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k int, v string) bool {
i++
return true
})
m.Iterator(func(k int, v string) bool {
j++
return false
})
gtest.Assert(i, 2)
gtest.Assert(j, 1)
}
func Test_IntStrMap_Lock(t *testing.T) {
expect := map[int]string{1: "a", 2: "b", 3: "c"}
m := gmap.NewIntStrMapFrom(expect)
m.LockFunc(func(m map[int]string) {
gtest.Assert(m, expect)
gtest.C(t, func(t *gtest.T) {
expect := map[int]string{1: "a", 2: "b", 3: "c"}
m := gmap.NewIntStrMapFrom(expect)
m.LockFunc(func(m map[int]string) {
t.Assert(m, expect)
})
m.RLockFunc(func(m map[int]string) {
t.Assert(m, expect)
})
})
m.RLockFunc(func(m map[int]string) {
gtest.Assert(m, expect)
})
}
func Test_IntStrMap_Clone(t *testing.T) {
//clone 方法是深克隆
m := gmap.NewIntStrMapFrom(map[int]string{1: "a", 2: "b", 3: "c"})
gtest.C(t, func(t *gtest.T) {
//clone 方法是深克隆
m := gmap.NewIntStrMapFrom(map[int]string{1: "a", 2: "b", 3: "c"})
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
gtest.AssertIN(1, m_clone.Keys())
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
t.AssertIN(1, m_clone.Keys())
m_clone.Remove(2)
//修改clone map,原 map 不影响
gtest.AssertIN(2, m.Keys())
m_clone.Remove(2)
//修改clone map,原 map 不影响
t.AssertIN(2, m.Keys())
})
}
func Test_IntStrMap_Merge(t *testing.T) {
m1 := gmap.NewIntStrMap()
m2 := gmap.NewIntStrMap()
m1.Set(1, "a")
m2.Set(2, "b")
m1.Merge(m2)
gtest.Assert(m1.Map(), map[int]string{1: "a", 2: "b"})
gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewIntStrMap()
m2 := gmap.NewIntStrMap()
m1.Set(1, "a")
m2.Set(2, "b")
m1.Merge(m2)
t.Assert(m1.Map(), map[int]string{1: "a", 2: "b"})
})
}
func Test_IntStrMap_Map(t *testing.T) {
m := gmap.NewIntStrMap()
m.Set(1, "0")
m.Set(2, "2")
gtest.Assert(m.Get(1), "0")
gtest.Assert(m.Get(2), "2")
data := m.Map()
gtest.Assert(data[1], "0")
gtest.Assert(data[2], "2")
data[3] = "3"
gtest.Assert(m.Get(3), "3")
m.Set(4, "4")
gtest.Assert(data[4], "4")
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMap()
m.Set(1, "0")
m.Set(2, "2")
t.Assert(m.Get(1), "0")
t.Assert(m.Get(2), "2")
data := m.Map()
t.Assert(data[1], "0")
t.Assert(data[2], "2")
data[3] = "3"
t.Assert(m.Get(3), "3")
m.Set(4, "4")
t.Assert(data[4], "4")
})
}
func Test_IntStrMap_MapCopy(t *testing.T) {
m := gmap.NewIntStrMap()
m.Set(1, "0")
m.Set(2, "2")
gtest.Assert(m.Get(1), "0")
gtest.Assert(m.Get(2), "2")
data := m.MapCopy()
gtest.Assert(data[1], "0")
gtest.Assert(data[2], "2")
data[3] = "3"
gtest.Assert(m.Get(3), "")
m.Set(4, "4")
gtest.Assert(data[4], "")
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMap()
m.Set(1, "0")
m.Set(2, "2")
t.Assert(m.Get(1), "0")
t.Assert(m.Get(2), "2")
data := m.MapCopy()
t.Assert(data[1], "0")
t.Assert(data[2], "2")
data[3] = "3"
t.Assert(m.Get(3), "")
m.Set(4, "4")
t.Assert(data[4], "")
})
}
func Test_IntStrMap_FilterEmpty(t *testing.T) {
m := gmap.NewIntStrMap()
m.Set(1, "")
m.Set(2, "2")
gtest.Assert(m.Size(), 2)
gtest.Assert(m.Get(2), "2")
m.FilterEmpty()
gtest.Assert(m.Size(), 1)
gtest.Assert(m.Get(2), "2")
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMap()
m.Set(1, "")
m.Set(2, "2")
t.Assert(m.Size(), 2)
t.Assert(m.Get(2), "2")
m.FilterEmpty()
t.Assert(m.Size(), 1)
t.Assert(m.Get(2), "2")
})
}
func Test_IntStrMap_Json(t *testing.T) {
// Marshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapIntStr{
1: "v1",
2: "v2",
@ -190,111 +204,111 @@ func Test_IntStrMap_Json(t *testing.T) {
m1 := gmap.NewIntStrMapFrom(data)
b1, err1 := json.Marshal(m1)
b2, err2 := json.Marshal(data)
gtest.Assert(err1, err2)
gtest.Assert(b1, b2)
t.Assert(err1, err2)
t.Assert(b1, b2)
})
// Unmarshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapIntStr{
1: "v1",
2: "v2",
}
b, err := json.Marshal(data)
gtest.Assert(err, nil)
t.Assert(err, nil)
m := gmap.NewIntStrMap()
err = json.Unmarshal(b, m)
gtest.Assert(err, nil)
gtest.Assert(m.Get(1), data[1])
gtest.Assert(m.Get(2), data[2])
t.Assert(err, nil)
t.Assert(m.Get(1), data[1])
t.Assert(m.Get(2), data[2])
})
}
func Test_IntStrMap_Pop(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMapFrom(g.MapIntStr{
1: "v1",
2: "v2",
})
gtest.Assert(m.Size(), 2)
t.Assert(m.Size(), 2)
k1, v1 := m.Pop()
gtest.AssertIN(k1, g.Slice{1, 2})
gtest.AssertIN(v1, g.Slice{"v1", "v2"})
gtest.Assert(m.Size(), 1)
t.AssertIN(k1, g.Slice{1, 2})
t.AssertIN(v1, g.Slice{"v1", "v2"})
t.Assert(m.Size(), 1)
k2, v2 := m.Pop()
gtest.AssertIN(k2, g.Slice{1, 2})
gtest.AssertIN(v2, g.Slice{"v1", "v2"})
gtest.Assert(m.Size(), 0)
t.AssertIN(k2, g.Slice{1, 2})
t.AssertIN(v2, g.Slice{"v1", "v2"})
t.Assert(m.Size(), 0)
gtest.AssertNE(k1, k2)
gtest.AssertNE(v1, v2)
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
})
}
func Test_IntStrMap_Pops(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntStrMapFrom(g.MapIntStr{
1: "v1",
2: "v2",
3: "v3",
})
gtest.Assert(m.Size(), 3)
t.Assert(m.Size(), 3)
kArray := garray.New()
vArray := garray.New()
for k, v := range m.Pops(1) {
gtest.AssertIN(k, g.Slice{1, 2, 3})
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
t.AssertIN(k, g.Slice{1, 2, 3})
t.AssertIN(v, g.Slice{"v1", "v2", "v3"})
kArray.Append(k)
vArray.Append(v)
}
gtest.Assert(m.Size(), 2)
t.Assert(m.Size(), 2)
for k, v := range m.Pops(2) {
gtest.AssertIN(k, g.Slice{1, 2, 3})
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
t.AssertIN(k, g.Slice{1, 2, 3})
t.AssertIN(v, g.Slice{"v1", "v2", "v3"})
kArray.Append(k)
vArray.Append(v)
}
gtest.Assert(m.Size(), 0)
t.Assert(m.Size(), 0)
gtest.Assert(kArray.Unique().Len(), 3)
gtest.Assert(vArray.Unique().Len(), 3)
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
})
}
func TestIntStrMap_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Map *gmap.IntStrMap
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"1":"v1","2":"v2"}`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get(1), "v1")
gtest.Assert(t.Map.Get(2), "v2")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get(1), "v1")
t.Assert(v.Map.Get(2), "v2")
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.MapIntAny{
1: "v1",
2: "v2",
},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get(1), "v1")
gtest.Assert(t.Map.Get(2), "v2")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get(1), "v1")
t.Assert(v.Map.Get(2), "v2")
})
}

View File

@ -18,125 +18,139 @@ import (
)
func Test_ListMap_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewListMap()
m.Set("key1", "val1")
gtest.Assert(m.Keys(), []interface{}{"key1"})
t.Assert(m.Keys(), []interface{}{"key1"})
gtest.Assert(m.Get("key1"), "val1")
gtest.Assert(m.Size(), 1)
gtest.Assert(m.IsEmpty(), false)
t.Assert(m.Get("key1"), "val1")
t.Assert(m.Size(), 1)
t.Assert(m.IsEmpty(), false)
gtest.Assert(m.GetOrSet("key2", "val2"), "val2")
gtest.Assert(m.SetIfNotExist("key2", "val2"), false)
t.Assert(m.GetOrSet("key2", "val2"), "val2")
t.Assert(m.SetIfNotExist("key2", "val2"), false)
gtest.Assert(m.SetIfNotExist("key3", "val3"), true)
gtest.Assert(m.Remove("key2"), "val2")
gtest.Assert(m.Contains("key2"), false)
t.Assert(m.SetIfNotExist("key3", "val3"), true)
t.Assert(m.Remove("key2"), "val2")
t.Assert(m.Contains("key2"), false)
gtest.AssertIN("key3", m.Keys())
gtest.AssertIN("key1", m.Keys())
gtest.AssertIN("val3", m.Values())
gtest.AssertIN("val1", m.Values())
t.AssertIN("key3", m.Keys())
t.AssertIN("key1", m.Keys())
t.AssertIN("val3", m.Values())
t.AssertIN("val1", m.Values())
m.Flip()
gtest.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val1": "key1"})
t.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val1": "key1"})
m.Clear()
gtest.Assert(m.Size(), 0)
gtest.Assert(m.IsEmpty(), true)
t.Assert(m.Size(), 0)
t.Assert(m.IsEmpty(), true)
m2 := gmap.NewListMapFrom(map[interface{}]interface{}{1: 1, "key1": "val1"})
gtest.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"})
t.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"})
})
}
func Test_ListMap_Set_Fun(t *testing.T) {
m := gmap.NewListMap()
m.GetOrSetFunc("fun", getValue)
m.GetOrSetFuncLock("funlock", getValue)
gtest.Assert(m.Get("funlock"), 3)
gtest.Assert(m.Get("fun"), 3)
m.GetOrSetFunc("fun", getValue)
gtest.Assert(m.SetIfNotExistFunc("fun", getValue), false)
gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewListMap()
m.GetOrSetFunc("fun", getValue)
m.GetOrSetFuncLock("funlock", getValue)
t.Assert(m.Get("funlock"), 3)
t.Assert(m.Get("fun"), 3)
m.GetOrSetFunc("fun", getValue)
t.Assert(m.SetIfNotExistFunc("fun", getValue), false)
t.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false)
})
}
func Test_ListMap_Batch(t *testing.T) {
m := gmap.NewListMap()
m.Sets(map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
gtest.Assert(m.Map(), map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
m.Removes([]interface{}{"key1", 1})
gtest.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewListMap()
m.Sets(map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
t.Assert(m.Map(), map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
m.Removes([]interface{}{"key1", 1})
t.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"})
})
}
func Test_ListMap_Iterator(t *testing.T) {
expect := map[interface{}]interface{}{1: 1, "key1": "val1"}
gtest.C(t, func(t *gtest.T) {
expect := map[interface{}]interface{}{1: 1, "key1": "val1"}
m := gmap.NewListMapFrom(expect)
m.Iterator(func(k interface{}, v interface{}) bool {
gtest.Assert(expect[k], v)
return true
m := gmap.NewListMapFrom(expect)
m.Iterator(func(k interface{}, v interface{}) bool {
t.Assert(expect[k], v)
return true
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k interface{}, v interface{}) bool {
i++
return true
})
m.Iterator(func(k interface{}, v interface{}) bool {
j++
return false
})
t.Assert(i, 2)
t.Assert(j, 1)
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k interface{}, v interface{}) bool {
i++
return true
})
m.Iterator(func(k interface{}, v interface{}) bool {
j++
return false
})
gtest.Assert(i, 2)
gtest.Assert(j, 1)
}
func Test_ListMap_Clone(t *testing.T) {
//clone 方法是深克隆
m := gmap.NewListMapFrom(map[interface{}]interface{}{1: 1, "key1": "val1"})
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
gtest.AssertIN(1, m_clone.Keys())
gtest.C(t, func(t *gtest.T) {
//clone 方法是深克隆
m := gmap.NewListMapFrom(map[interface{}]interface{}{1: 1, "key1": "val1"})
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
t.AssertIN(1, m_clone.Keys())
m_clone.Remove("key1")
//修改clone map,原 map 不影响
gtest.AssertIN("key1", m.Keys())
m_clone.Remove("key1")
//修改clone map,原 map 不影响
t.AssertIN("key1", m.Keys())
})
}
func Test_ListMap_Basic_Merge(t *testing.T) {
m1 := gmap.NewListMap()
m2 := gmap.NewListMap()
m1.Set("key1", "val1")
m2.Set("key2", "val2")
m1.Merge(m2)
gtest.Assert(m1.Map(), map[interface{}]interface{}{"key1": "val1", "key2": "val2"})
gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewListMap()
m2 := gmap.NewListMap()
m1.Set("key1", "val1")
m2.Set("key2", "val2")
m1.Merge(m2)
t.Assert(m1.Map(), map[interface{}]interface{}{"key1": "val1", "key2": "val2"})
})
}
func Test_ListMap_Order(t *testing.T) {
m := gmap.NewListMap()
m.Set("k1", "v1")
m.Set("k2", "v2")
m.Set("k3", "v3")
gtest.Assert(m.Keys(), g.Slice{"k1", "k2", "k3"})
gtest.Assert(m.Values(), g.Slice{"v1", "v2", "v3"})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewListMap()
m.Set("k1", "v1")
m.Set("k2", "v2")
m.Set("k3", "v3")
t.Assert(m.Keys(), g.Slice{"k1", "k2", "k3"})
t.Assert(m.Values(), g.Slice{"v1", "v2", "v3"})
})
}
func Test_ListMap_FilterEmpty(t *testing.T) {
m := gmap.NewListMap()
m.Set(1, "")
m.Set(2, "2")
gtest.Assert(m.Size(), 2)
gtest.Assert(m.Get(2), "2")
m.FilterEmpty()
gtest.Assert(m.Size(), 1)
gtest.Assert(m.Get(2), "2")
gtest.C(t, func(t *gtest.T) {
m := gmap.NewListMap()
m.Set(1, "")
m.Set(2, "2")
t.Assert(m.Size(), 2)
t.Assert(m.Get(2), "2")
m.FilterEmpty()
t.Assert(m.Size(), 1)
t.Assert(m.Get(2), "2")
})
}
func Test_ListMap_Json(t *testing.T) {
// Marshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapAnyAny{
"k1": "v1",
"k2": "v2",
@ -144,126 +158,126 @@ func Test_ListMap_Json(t *testing.T) {
m1 := gmap.NewListMapFrom(data)
b1, err1 := json.Marshal(m1)
b2, err2 := json.Marshal(gconv.Map(data))
gtest.Assert(err1, err2)
gtest.Assert(b1, b2)
t.Assert(err1, err2)
t.Assert(b1, b2)
})
// Unmarshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapAnyAny{
"k1": "v1",
"k2": "v2",
}
b, err := json.Marshal(gconv.Map(data))
gtest.Assert(err, nil)
t.Assert(err, nil)
m := gmap.NewListMap()
err = json.Unmarshal(b, m)
gtest.Assert(err, nil)
gtest.Assert(m.Get("k1"), data["k1"])
gtest.Assert(m.Get("k2"), data["k2"])
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapAnyAny{
"k1": "v1",
"k2": "v2",
}
b, err := json.Marshal(gconv.Map(data))
gtest.Assert(err, nil)
t.Assert(err, nil)
var m gmap.ListMap
err = json.Unmarshal(b, &m)
gtest.Assert(err, nil)
gtest.Assert(m.Get("k1"), data["k1"])
gtest.Assert(m.Get("k2"), data["k2"])
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
})
}
func Test_ListMap_Pop(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewListMapFrom(g.MapAnyAny{
"k1": "v1",
"k2": "v2",
})
gtest.Assert(m.Size(), 2)
t.Assert(m.Size(), 2)
k1, v1 := m.Pop()
gtest.AssertIN(k1, g.Slice{"k1", "k2"})
gtest.AssertIN(v1, g.Slice{"v1", "v2"})
gtest.Assert(m.Size(), 1)
t.AssertIN(k1, g.Slice{"k1", "k2"})
t.AssertIN(v1, g.Slice{"v1", "v2"})
t.Assert(m.Size(), 1)
k2, v2 := m.Pop()
gtest.AssertIN(k2, g.Slice{"k1", "k2"})
gtest.AssertIN(v2, g.Slice{"v1", "v2"})
gtest.Assert(m.Size(), 0)
t.AssertIN(k2, g.Slice{"k1", "k2"})
t.AssertIN(v2, g.Slice{"v1", "v2"})
t.Assert(m.Size(), 0)
gtest.AssertNE(k1, k2)
gtest.AssertNE(v1, v2)
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
})
}
func Test_ListMap_Pops(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewListMapFrom(g.MapAnyAny{
"k1": "v1",
"k2": "v2",
"k3": "v3",
})
gtest.Assert(m.Size(), 3)
t.Assert(m.Size(), 3)
kArray := garray.New()
vArray := garray.New()
for k, v := range m.Pops(1) {
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
t.AssertIN(k, g.Slice{"k1", "k2", "k3"})
t.AssertIN(v, g.Slice{"v1", "v2", "v3"})
kArray.Append(k)
vArray.Append(v)
}
gtest.Assert(m.Size(), 2)
t.Assert(m.Size(), 2)
for k, v := range m.Pops(2) {
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
t.AssertIN(k, g.Slice{"k1", "k2", "k3"})
t.AssertIN(v, g.Slice{"v1", "v2", "v3"})
kArray.Append(k)
vArray.Append(v)
}
gtest.Assert(m.Size(), 0)
t.Assert(m.Size(), 0)
gtest.Assert(kArray.Unique().Len(), 3)
gtest.Assert(vArray.Unique().Len(), 3)
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
})
}
func TestListMap_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Map *gmap.ListMap
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"1":"v1","2":"v2"}`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get("1"), "v1")
gtest.Assert(t.Map.Get("2"), "v2")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get("1"), "v1")
t.Assert(v.Map.Get("2"), "v2")
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.MapIntAny{
1: "v1",
2: "v2",
},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get("1"), "v1")
gtest.Assert(t.Map.Get("2"), "v2")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get("1"), "v1")
t.Assert(v.Map.Get("2"), "v2")
})
}

View File

@ -21,162 +21,179 @@ func stringAnyCallBack(string, interface{}) bool {
return true
}
func Test_StrAnyMap_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrAnyMap()
m.Set("a", 1)
gtest.Assert(m.Get("a"), 1)
gtest.Assert(m.Size(), 1)
gtest.Assert(m.IsEmpty(), false)
t.Assert(m.Get("a"), 1)
t.Assert(m.Size(), 1)
t.Assert(m.IsEmpty(), false)
gtest.Assert(m.GetOrSet("b", "2"), "2")
gtest.Assert(m.SetIfNotExist("b", "2"), false)
t.Assert(m.GetOrSet("b", "2"), "2")
t.Assert(m.SetIfNotExist("b", "2"), false)
gtest.Assert(m.SetIfNotExist("c", 3), true)
t.Assert(m.SetIfNotExist("c", 3), true)
gtest.Assert(m.Remove("b"), "2")
gtest.Assert(m.Contains("b"), false)
t.Assert(m.Remove("b"), "2")
t.Assert(m.Contains("b"), false)
gtest.AssertIN("c", m.Keys())
gtest.AssertIN("a", m.Keys())
gtest.AssertIN(3, m.Values())
gtest.AssertIN(1, m.Values())
t.AssertIN("c", m.Keys())
t.AssertIN("a", m.Keys())
t.AssertIN(3, m.Values())
t.AssertIN(1, m.Values())
m.Flip()
gtest.Assert(m.Map(), map[string]interface{}{"1": "a", "3": "c"})
t.Assert(m.Map(), map[string]interface{}{"1": "a", "3": "c"})
m.Clear()
gtest.Assert(m.Size(), 0)
gtest.Assert(m.IsEmpty(), true)
t.Assert(m.Size(), 0)
t.Assert(m.IsEmpty(), true)
m2 := gmap.NewStrAnyMapFrom(map[string]interface{}{"a": 1, "b": "2"})
gtest.Assert(m2.Map(), map[string]interface{}{"a": 1, "b": "2"})
t.Assert(m2.Map(), map[string]interface{}{"a": 1, "b": "2"})
})
}
func Test_StrAnyMap_Set_Fun(t *testing.T) {
m := gmap.NewStrAnyMap()
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrAnyMap()
m.GetOrSetFunc("a", getAny)
m.GetOrSetFuncLock("b", getAny)
gtest.Assert(m.Get("a"), 123)
gtest.Assert(m.Get("b"), 123)
gtest.Assert(m.SetIfNotExistFunc("a", getAny), false)
gtest.Assert(m.SetIfNotExistFunc("c", getAny), true)
gtest.Assert(m.SetIfNotExistFuncLock("b", getAny), false)
gtest.Assert(m.SetIfNotExistFuncLock("d", getAny), true)
m.GetOrSetFunc("a", getAny)
m.GetOrSetFuncLock("b", getAny)
t.Assert(m.Get("a"), 123)
t.Assert(m.Get("b"), 123)
t.Assert(m.SetIfNotExistFunc("a", getAny), false)
t.Assert(m.SetIfNotExistFunc("c", getAny), true)
t.Assert(m.SetIfNotExistFuncLock("b", getAny), false)
t.Assert(m.SetIfNotExistFuncLock("d", getAny), true)
})
}
func Test_StrAnyMap_Batch(t *testing.T) {
m := gmap.NewStrAnyMap()
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrAnyMap()
m.Sets(map[string]interface{}{"a": 1, "b": "2", "c": 3})
gtest.Assert(m.Map(), map[string]interface{}{"a": 1, "b": "2", "c": 3})
m.Removes([]string{"a", "b"})
gtest.Assert(m.Map(), map[string]interface{}{"c": 3})
m.Sets(map[string]interface{}{"a": 1, "b": "2", "c": 3})
t.Assert(m.Map(), map[string]interface{}{"a": 1, "b": "2", "c": 3})
m.Removes([]string{"a", "b"})
t.Assert(m.Map(), map[string]interface{}{"c": 3})
})
}
func Test_StrAnyMap_Iterator(t *testing.T) {
expect := map[string]interface{}{"a": true, "b": false}
m := gmap.NewStrAnyMapFrom(expect)
m.Iterator(func(k string, v interface{}) bool {
gtest.Assert(expect[k], v)
return true
gtest.C(t, func(t *gtest.T) {
expect := map[string]interface{}{"a": true, "b": false}
m := gmap.NewStrAnyMapFrom(expect)
m.Iterator(func(k string, v interface{}) bool {
t.Assert(expect[k], v)
return true
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k string, v interface{}) bool {
i++
return true
})
m.Iterator(func(k string, v interface{}) bool {
j++
return false
})
t.Assert(i, 2)
t.Assert(j, 1)
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k string, v interface{}) bool {
i++
return true
})
m.Iterator(func(k string, v interface{}) bool {
j++
return false
})
gtest.Assert(i, 2)
gtest.Assert(j, 1)
}
func Test_StrAnyMap_Lock(t *testing.T) {
expect := map[string]interface{}{"a": true, "b": false}
gtest.C(t, func(t *gtest.T) {
expect := map[string]interface{}{"a": true, "b": false}
m := gmap.NewStrAnyMapFrom(expect)
m.LockFunc(func(m map[string]interface{}) {
gtest.Assert(m, expect)
})
m.RLockFunc(func(m map[string]interface{}) {
gtest.Assert(m, expect)
m := gmap.NewStrAnyMapFrom(expect)
m.LockFunc(func(m map[string]interface{}) {
t.Assert(m, expect)
})
m.RLockFunc(func(m map[string]interface{}) {
t.Assert(m, expect)
})
})
}
func Test_StrAnyMap_Clone(t *testing.T) {
//clone 方法是深克隆
m := gmap.NewStrAnyMapFrom(map[string]interface{}{"a": 1, "b": "2"})
gtest.C(t, func(t *gtest.T) {
//clone 方法是深克隆
m := gmap.NewStrAnyMapFrom(map[string]interface{}{"a": 1, "b": "2"})
m_clone := m.Clone()
m.Remove("a")
//修改原 map,clone 后的 map 不影响
gtest.AssertIN("a", m_clone.Keys())
m_clone := m.Clone()
m.Remove("a")
//修改原 map,clone 后的 map 不影响
t.AssertIN("a", m_clone.Keys())
m_clone.Remove("b")
//修改clone map,原 map 不影响
gtest.AssertIN("b", m.Keys())
m_clone.Remove("b")
//修改clone map,原 map 不影响
t.AssertIN("b", m.Keys())
})
}
func Test_StrAnyMap_Merge(t *testing.T) {
m1 := gmap.NewStrAnyMap()
m2 := gmap.NewStrAnyMap()
m1.Set("a", 1)
m2.Set("b", "2")
m1.Merge(m2)
gtest.Assert(m1.Map(), map[string]interface{}{"a": 1, "b": "2"})
gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewStrAnyMap()
m2 := gmap.NewStrAnyMap()
m1.Set("a", 1)
m2.Set("b", "2")
m1.Merge(m2)
t.Assert(m1.Map(), map[string]interface{}{"a": 1, "b": "2"})
})
}
func Test_StrAnyMap_Map(t *testing.T) {
m := gmap.NewStrAnyMap()
m.Set("1", 1)
m.Set("2", 2)
gtest.Assert(m.Get("1"), 1)
gtest.Assert(m.Get("2"), 2)
data := m.Map()
gtest.Assert(data["1"], 1)
gtest.Assert(data["2"], 2)
data["3"] = 3
gtest.Assert(m.Get("3"), 3)
m.Set("4", 4)
gtest.Assert(data["4"], 4)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrAnyMap()
m.Set("1", 1)
m.Set("2", 2)
t.Assert(m.Get("1"), 1)
t.Assert(m.Get("2"), 2)
data := m.Map()
t.Assert(data["1"], 1)
t.Assert(data["2"], 2)
data["3"] = 3
t.Assert(m.Get("3"), 3)
m.Set("4", 4)
t.Assert(data["4"], 4)
})
}
func Test_StrAnyMap_MapCopy(t *testing.T) {
m := gmap.NewStrAnyMap()
m.Set("1", 1)
m.Set("2", 2)
gtest.Assert(m.Get("1"), 1)
gtest.Assert(m.Get("2"), 2)
data := m.MapCopy()
gtest.Assert(data["1"], 1)
gtest.Assert(data["2"], 2)
data["3"] = 3
gtest.Assert(m.Get("3"), nil)
m.Set("4", 4)
gtest.Assert(data["4"], nil)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrAnyMap()
m.Set("1", 1)
m.Set("2", 2)
t.Assert(m.Get("1"), 1)
t.Assert(m.Get("2"), 2)
data := m.MapCopy()
t.Assert(data["1"], 1)
t.Assert(data["2"], 2)
data["3"] = 3
t.Assert(m.Get("3"), nil)
m.Set("4", 4)
t.Assert(data["4"], nil)
})
}
func Test_StrAnyMap_FilterEmpty(t *testing.T) {
m := gmap.NewStrAnyMap()
m.Set("1", 0)
m.Set("2", 2)
gtest.Assert(m.Size(), 2)
gtest.Assert(m.Get("1"), 0)
gtest.Assert(m.Get("2"), 2)
m.FilterEmpty()
gtest.Assert(m.Size(), 1)
gtest.Assert(m.Get("2"), 2)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrAnyMap()
m.Set("1", 0)
m.Set("2", 2)
t.Assert(m.Size(), 2)
t.Assert(m.Get("1"), 0)
t.Assert(m.Get("2"), 2)
m.FilterEmpty()
t.Assert(m.Size(), 1)
t.Assert(m.Get("2"), 2)
})
}
func Test_StrAnyMap_Json(t *testing.T) {
// Marshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapStrAny{
"k1": "v1",
"k2": "v2",
@ -184,125 +201,125 @@ func Test_StrAnyMap_Json(t *testing.T) {
m1 := gmap.NewStrAnyMapFrom(data)
b1, err1 := json.Marshal(m1)
b2, err2 := json.Marshal(data)
gtest.Assert(err1, err2)
gtest.Assert(b1, b2)
t.Assert(err1, err2)
t.Assert(b1, b2)
})
// Unmarshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapStrAny{
"k1": "v1",
"k2": "v2",
}
b, err := json.Marshal(data)
gtest.Assert(err, nil)
t.Assert(err, nil)
m := gmap.NewStrAnyMap()
err = json.Unmarshal(b, m)
gtest.Assert(err, nil)
gtest.Assert(m.Get("k1"), data["k1"])
gtest.Assert(m.Get("k2"), data["k2"])
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapStrAny{
"k1": "v1",
"k2": "v2",
}
b, err := json.Marshal(data)
gtest.Assert(err, nil)
t.Assert(err, nil)
var m gmap.StrAnyMap
err = json.Unmarshal(b, &m)
gtest.Assert(err, nil)
gtest.Assert(m.Get("k1"), data["k1"])
gtest.Assert(m.Get("k2"), data["k2"])
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
})
}
func Test_StrAnyMap_Pop(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrAnyMapFrom(g.MapStrAny{
"k1": "v1",
"k2": "v2",
})
gtest.Assert(m.Size(), 2)
t.Assert(m.Size(), 2)
k1, v1 := m.Pop()
gtest.AssertIN(k1, g.Slice{"k1", "k2"})
gtest.AssertIN(v1, g.Slice{"v1", "v2"})
gtest.Assert(m.Size(), 1)
t.AssertIN(k1, g.Slice{"k1", "k2"})
t.AssertIN(v1, g.Slice{"v1", "v2"})
t.Assert(m.Size(), 1)
k2, v2 := m.Pop()
gtest.AssertIN(k2, g.Slice{"k1", "k2"})
gtest.AssertIN(v2, g.Slice{"v1", "v2"})
gtest.Assert(m.Size(), 0)
t.AssertIN(k2, g.Slice{"k1", "k2"})
t.AssertIN(v2, g.Slice{"v1", "v2"})
t.Assert(m.Size(), 0)
gtest.AssertNE(k1, k2)
gtest.AssertNE(v1, v2)
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
})
}
func Test_StrAnyMap_Pops(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrAnyMapFrom(g.MapStrAny{
"k1": "v1",
"k2": "v2",
"k3": "v3",
})
gtest.Assert(m.Size(), 3)
t.Assert(m.Size(), 3)
kArray := garray.New()
vArray := garray.New()
for k, v := range m.Pops(1) {
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
t.AssertIN(k, g.Slice{"k1", "k2", "k3"})
t.AssertIN(v, g.Slice{"v1", "v2", "v3"})
kArray.Append(k)
vArray.Append(v)
}
gtest.Assert(m.Size(), 2)
t.Assert(m.Size(), 2)
for k, v := range m.Pops(2) {
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
t.AssertIN(k, g.Slice{"k1", "k2", "k3"})
t.AssertIN(v, g.Slice{"v1", "v2", "v3"})
kArray.Append(k)
vArray.Append(v)
}
gtest.Assert(m.Size(), 0)
t.Assert(m.Size(), 0)
gtest.Assert(kArray.Unique().Len(), 3)
gtest.Assert(vArray.Unique().Len(), 3)
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
})
}
func TestStrAnyMap_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Map *gmap.StrAnyMap
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"k1":"v1","k2":"v2"}`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get("k1"), "v1")
gtest.Assert(t.Map.Get("k2"), "v2")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get("k1"), "v1")
t.Assert(v.Map.Get("k2"), "v2")
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.Map{
"k1": "v1",
"k2": "v2",
},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get("k1"), "v1")
gtest.Assert(t.Map.Get("k2"), "v2")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get("k1"), "v1")
t.Assert(v.Map.Get("k2"), "v2")
})
}

View File

@ -21,165 +21,181 @@ func stringIntCallBack(string, int) bool {
return true
}
func Test_StrIntMap_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrIntMap()
m.Set("a", 1)
gtest.Assert(m.Get("a"), 1)
gtest.Assert(m.Size(), 1)
gtest.Assert(m.IsEmpty(), false)
t.Assert(m.Get("a"), 1)
t.Assert(m.Size(), 1)
t.Assert(m.IsEmpty(), false)
gtest.Assert(m.GetOrSet("b", 2), 2)
gtest.Assert(m.SetIfNotExist("b", 2), false)
t.Assert(m.GetOrSet("b", 2), 2)
t.Assert(m.SetIfNotExist("b", 2), false)
gtest.Assert(m.SetIfNotExist("c", 3), true)
t.Assert(m.SetIfNotExist("c", 3), true)
gtest.Assert(m.Remove("b"), 2)
gtest.Assert(m.Contains("b"), false)
t.Assert(m.Remove("b"), 2)
t.Assert(m.Contains("b"), false)
gtest.AssertIN("c", m.Keys())
gtest.AssertIN("a", m.Keys())
gtest.AssertIN(3, m.Values())
gtest.AssertIN(1, m.Values())
t.AssertIN("c", m.Keys())
t.AssertIN("a", m.Keys())
t.AssertIN(3, m.Values())
t.AssertIN(1, m.Values())
m_f := gmap.NewStrIntMap()
m_f.Set("1", 2)
m_f.Flip()
gtest.Assert(m_f.Map(), map[string]int{"2": 1})
t.Assert(m_f.Map(), map[string]int{"2": 1})
m.Clear()
gtest.Assert(m.Size(), 0)
gtest.Assert(m.IsEmpty(), true)
t.Assert(m.Size(), 0)
t.Assert(m.IsEmpty(), true)
m2 := gmap.NewStrIntMapFrom(map[string]int{"a": 1, "b": 2})
gtest.Assert(m2.Map(), map[string]int{"a": 1, "b": 2})
t.Assert(m2.Map(), map[string]int{"a": 1, "b": 2})
})
}
func Test_StrIntMap_Set_Fun(t *testing.T) {
m := gmap.NewStrIntMap()
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrIntMap()
m.GetOrSetFunc("a", getInt)
m.GetOrSetFuncLock("b", getInt)
gtest.Assert(m.Get("a"), 123)
gtest.Assert(m.Get("b"), 123)
gtest.Assert(m.SetIfNotExistFunc("a", getInt), false)
gtest.Assert(m.SetIfNotExistFunc("c", getInt), true)
gtest.Assert(m.SetIfNotExistFuncLock("b", getInt), false)
gtest.Assert(m.SetIfNotExistFuncLock("d", getInt), true)
m.GetOrSetFunc("a", getInt)
m.GetOrSetFuncLock("b", getInt)
t.Assert(m.Get("a"), 123)
t.Assert(m.Get("b"), 123)
t.Assert(m.SetIfNotExistFunc("a", getInt), false)
t.Assert(m.SetIfNotExistFunc("c", getInt), true)
t.Assert(m.SetIfNotExistFuncLock("b", getInt), false)
t.Assert(m.SetIfNotExistFuncLock("d", getInt), true)
})
}
func Test_StrIntMap_Batch(t *testing.T) {
m := gmap.NewStrIntMap()
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrIntMap()
m.Sets(map[string]int{"a": 1, "b": 2, "c": 3})
gtest.Assert(m.Map(), map[string]int{"a": 1, "b": 2, "c": 3})
m.Removes([]string{"a", "b"})
gtest.Assert(m.Map(), map[string]int{"c": 3})
m.Sets(map[string]int{"a": 1, "b": 2, "c": 3})
t.Assert(m.Map(), map[string]int{"a": 1, "b": 2, "c": 3})
m.Removes([]string{"a", "b"})
t.Assert(m.Map(), map[string]int{"c": 3})
})
}
func Test_StrIntMap_Iterator(t *testing.T) {
expect := map[string]int{"a": 1, "b": 2}
m := gmap.NewStrIntMapFrom(expect)
m.Iterator(func(k string, v int) bool {
gtest.Assert(expect[k], v)
return true
gtest.C(t, func(t *gtest.T) {
expect := map[string]int{"a": 1, "b": 2}
m := gmap.NewStrIntMapFrom(expect)
m.Iterator(func(k string, v int) bool {
t.Assert(expect[k], v)
return true
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k string, v int) bool {
i++
return true
})
m.Iterator(func(k string, v int) bool {
j++
return false
})
t.Assert(i, 2)
t.Assert(j, 1)
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k string, v int) bool {
i++
return true
})
m.Iterator(func(k string, v int) bool {
j++
return false
})
gtest.Assert(i, 2)
gtest.Assert(j, 1)
}
func Test_StrIntMap_Lock(t *testing.T) {
expect := map[string]int{"a": 1, "b": 2}
gtest.C(t, func(t *gtest.T) {
expect := map[string]int{"a": 1, "b": 2}
m := gmap.NewStrIntMapFrom(expect)
m.LockFunc(func(m map[string]int) {
gtest.Assert(m, expect)
})
m.RLockFunc(func(m map[string]int) {
gtest.Assert(m, expect)
m := gmap.NewStrIntMapFrom(expect)
m.LockFunc(func(m map[string]int) {
t.Assert(m, expect)
})
m.RLockFunc(func(m map[string]int) {
t.Assert(m, expect)
})
})
}
func Test_StrIntMap_Clone(t *testing.T) {
//clone 方法是深克隆
m := gmap.NewStrIntMapFrom(map[string]int{"a": 1, "b": 2, "c": 3})
gtest.C(t, func(t *gtest.T) {
//clone 方法是深克隆
m := gmap.NewStrIntMapFrom(map[string]int{"a": 1, "b": 2, "c": 3})
m_clone := m.Clone()
m.Remove("a")
//修改原 map,clone 后的 map 不影响
gtest.AssertIN("a", m_clone.Keys())
m_clone := m.Clone()
m.Remove("a")
//修改原 map,clone 后的 map 不影响
t.AssertIN("a", m_clone.Keys())
m_clone.Remove("b")
//修改clone map,原 map 不影响
gtest.AssertIN("b", m.Keys())
m_clone.Remove("b")
//修改clone map,原 map 不影响
t.AssertIN("b", m.Keys())
})
}
func Test_StrIntMap_Merge(t *testing.T) {
m1 := gmap.NewStrIntMap()
m2 := gmap.NewStrIntMap()
m1.Set("a", 1)
m2.Set("b", 2)
m1.Merge(m2)
gtest.Assert(m1.Map(), map[string]int{"a": 1, "b": 2})
gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewStrIntMap()
m2 := gmap.NewStrIntMap()
m1.Set("a", 1)
m2.Set("b", 2)
m1.Merge(m2)
t.Assert(m1.Map(), map[string]int{"a": 1, "b": 2})
})
}
func Test_StrIntMap_Map(t *testing.T) {
m := gmap.NewStrIntMap()
m.Set("1", 1)
m.Set("2", 2)
gtest.Assert(m.Get("1"), 1)
gtest.Assert(m.Get("2"), 2)
data := m.Map()
gtest.Assert(data["1"], 1)
gtest.Assert(data["2"], 2)
data["3"] = 3
gtest.Assert(m.Get("3"), 3)
m.Set("4", 4)
gtest.Assert(data["4"], 4)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrIntMap()
m.Set("1", 1)
m.Set("2", 2)
t.Assert(m.Get("1"), 1)
t.Assert(m.Get("2"), 2)
data := m.Map()
t.Assert(data["1"], 1)
t.Assert(data["2"], 2)
data["3"] = 3
t.Assert(m.Get("3"), 3)
m.Set("4", 4)
t.Assert(data["4"], 4)
})
}
func Test_StrIntMap_MapCopy(t *testing.T) {
m := gmap.NewStrIntMap()
m.Set("1", 1)
m.Set("2", 2)
gtest.Assert(m.Get("1"), 1)
gtest.Assert(m.Get("2"), 2)
data := m.MapCopy()
gtest.Assert(data["1"], 1)
gtest.Assert(data["2"], 2)
data["3"] = 3
gtest.Assert(m.Get("3"), 0)
m.Set("4", 4)
gtest.Assert(data["4"], 0)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrIntMap()
m.Set("1", 1)
m.Set("2", 2)
t.Assert(m.Get("1"), 1)
t.Assert(m.Get("2"), 2)
data := m.MapCopy()
t.Assert(data["1"], 1)
t.Assert(data["2"], 2)
data["3"] = 3
t.Assert(m.Get("3"), 0)
m.Set("4", 4)
t.Assert(data["4"], 0)
})
}
func Test_StrIntMap_FilterEmpty(t *testing.T) {
m := gmap.NewStrIntMap()
m.Set("1", 0)
m.Set("2", 2)
gtest.Assert(m.Size(), 2)
gtest.Assert(m.Get("1"), 0)
gtest.Assert(m.Get("2"), 2)
m.FilterEmpty()
gtest.Assert(m.Size(), 1)
gtest.Assert(m.Get("2"), 2)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrIntMap()
m.Set("1", 0)
m.Set("2", 2)
t.Assert(m.Size(), 2)
t.Assert(m.Get("1"), 0)
t.Assert(m.Get("2"), 2)
m.FilterEmpty()
t.Assert(m.Size(), 1)
t.Assert(m.Get("2"), 2)
})
}
func Test_StrIntMap_Json(t *testing.T) {
// Marshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapStrInt{
"k1": 1,
"k2": 2,
@ -187,125 +203,125 @@ func Test_StrIntMap_Json(t *testing.T) {
m1 := gmap.NewStrIntMapFrom(data)
b1, err1 := json.Marshal(m1)
b2, err2 := json.Marshal(data)
gtest.Assert(err1, err2)
gtest.Assert(b1, b2)
t.Assert(err1, err2)
t.Assert(b1, b2)
})
// Unmarshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapStrInt{
"k1": 1,
"k2": 2,
}
b, err := json.Marshal(data)
gtest.Assert(err, nil)
t.Assert(err, nil)
m := gmap.NewStrIntMap()
err = json.Unmarshal(b, m)
gtest.Assert(err, nil)
gtest.Assert(m.Get("k1"), data["k1"])
gtest.Assert(m.Get("k2"), data["k2"])
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapStrInt{
"k1": 1,
"k2": 2,
}
b, err := json.Marshal(data)
gtest.Assert(err, nil)
t.Assert(err, nil)
var m gmap.StrIntMap
err = json.Unmarshal(b, &m)
gtest.Assert(err, nil)
gtest.Assert(m.Get("k1"), data["k1"])
gtest.Assert(m.Get("k2"), data["k2"])
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
})
}
func Test_StrIntMap_Pop(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrIntMapFrom(g.MapStrInt{
"k1": 11,
"k2": 22,
})
gtest.Assert(m.Size(), 2)
t.Assert(m.Size(), 2)
k1, v1 := m.Pop()
gtest.AssertIN(k1, g.Slice{"k1", "k2"})
gtest.AssertIN(v1, g.Slice{11, 22})
gtest.Assert(m.Size(), 1)
t.AssertIN(k1, g.Slice{"k1", "k2"})
t.AssertIN(v1, g.Slice{11, 22})
t.Assert(m.Size(), 1)
k2, v2 := m.Pop()
gtest.AssertIN(k2, g.Slice{"k1", "k2"})
gtest.AssertIN(v2, g.Slice{11, 22})
gtest.Assert(m.Size(), 0)
t.AssertIN(k2, g.Slice{"k1", "k2"})
t.AssertIN(v2, g.Slice{11, 22})
t.Assert(m.Size(), 0)
gtest.AssertNE(k1, k2)
gtest.AssertNE(v1, v2)
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
})
}
func Test_StrIntMap_Pops(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrIntMapFrom(g.MapStrInt{
"k1": 11,
"k2": 22,
"k3": 33,
})
gtest.Assert(m.Size(), 3)
t.Assert(m.Size(), 3)
kArray := garray.New()
vArray := garray.New()
for k, v := range m.Pops(1) {
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
gtest.AssertIN(v, g.Slice{11, 22, 33})
t.AssertIN(k, g.Slice{"k1", "k2", "k3"})
t.AssertIN(v, g.Slice{11, 22, 33})
kArray.Append(k)
vArray.Append(v)
}
gtest.Assert(m.Size(), 2)
t.Assert(m.Size(), 2)
for k, v := range m.Pops(2) {
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
gtest.AssertIN(v, g.Slice{11, 22, 33})
t.AssertIN(k, g.Slice{"k1", "k2", "k3"})
t.AssertIN(v, g.Slice{11, 22, 33})
kArray.Append(k)
vArray.Append(v)
}
gtest.Assert(m.Size(), 0)
t.Assert(m.Size(), 0)
gtest.Assert(kArray.Unique().Len(), 3)
gtest.Assert(vArray.Unique().Len(), 3)
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
})
}
func TestStrIntMap_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Map *gmap.StrIntMap
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"k1":1,"k2":2}`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get("k1"), 1)
gtest.Assert(t.Map.Get("k2"), 2)
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get("k1"), 1)
t.Assert(v.Map.Get("k2"), 2)
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.Map{
"k1": 1,
"k2": 2,
},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get("k1"), 1)
gtest.Assert(t.Map.Get("k2"), 2)
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get("k1"), 1)
t.Assert(v.Map.Get("k2"), 2)
})
}

View File

@ -21,162 +21,179 @@ func stringStrCallBack(string, string) bool {
return true
}
func Test_StrStrMap_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrStrMap()
m.Set("a", "a")
gtest.Assert(m.Get("a"), "a")
gtest.Assert(m.Size(), 1)
gtest.Assert(m.IsEmpty(), false)
t.Assert(m.Get("a"), "a")
t.Assert(m.Size(), 1)
t.Assert(m.IsEmpty(), false)
gtest.Assert(m.GetOrSet("b", "b"), "b")
gtest.Assert(m.SetIfNotExist("b", "b"), false)
t.Assert(m.GetOrSet("b", "b"), "b")
t.Assert(m.SetIfNotExist("b", "b"), false)
gtest.Assert(m.SetIfNotExist("c", "c"), true)
t.Assert(m.SetIfNotExist("c", "c"), true)
gtest.Assert(m.Remove("b"), "b")
gtest.Assert(m.Contains("b"), false)
t.Assert(m.Remove("b"), "b")
t.Assert(m.Contains("b"), false)
gtest.AssertIN("c", m.Keys())
gtest.AssertIN("a", m.Keys())
gtest.AssertIN("a", m.Values())
gtest.AssertIN("c", m.Values())
t.AssertIN("c", m.Keys())
t.AssertIN("a", m.Keys())
t.AssertIN("a", m.Values())
t.AssertIN("c", m.Values())
m.Flip()
gtest.Assert(m.Map(), map[string]string{"a": "a", "c": "c"})
t.Assert(m.Map(), map[string]string{"a": "a", "c": "c"})
m.Clear()
gtest.Assert(m.Size(), 0)
gtest.Assert(m.IsEmpty(), true)
t.Assert(m.Size(), 0)
t.Assert(m.IsEmpty(), true)
m2 := gmap.NewStrStrMapFrom(map[string]string{"a": "a", "b": "b"})
gtest.Assert(m2.Map(), map[string]string{"a": "a", "b": "b"})
t.Assert(m2.Map(), map[string]string{"a": "a", "b": "b"})
})
}
func Test_StrStrMap_Set_Fun(t *testing.T) {
m := gmap.NewStrStrMap()
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrStrMap()
m.GetOrSetFunc("a", getStr)
m.GetOrSetFuncLock("b", getStr)
gtest.Assert(m.Get("a"), "z")
gtest.Assert(m.Get("b"), "z")
gtest.Assert(m.SetIfNotExistFunc("a", getStr), false)
gtest.Assert(m.SetIfNotExistFunc("c", getStr), true)
gtest.Assert(m.SetIfNotExistFuncLock("b", getStr), false)
gtest.Assert(m.SetIfNotExistFuncLock("d", getStr), true)
m.GetOrSetFunc("a", getStr)
m.GetOrSetFuncLock("b", getStr)
t.Assert(m.Get("a"), "z")
t.Assert(m.Get("b"), "z")
t.Assert(m.SetIfNotExistFunc("a", getStr), false)
t.Assert(m.SetIfNotExistFunc("c", getStr), true)
t.Assert(m.SetIfNotExistFuncLock("b", getStr), false)
t.Assert(m.SetIfNotExistFuncLock("d", getStr), true)
})
}
func Test_StrStrMap_Batch(t *testing.T) {
m := gmap.NewStrStrMap()
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrStrMap()
m.Sets(map[string]string{"a": "a", "b": "b", "c": "c"})
gtest.Assert(m.Map(), map[string]string{"a": "a", "b": "b", "c": "c"})
m.Removes([]string{"a", "b"})
gtest.Assert(m.Map(), map[string]string{"c": "c"})
m.Sets(map[string]string{"a": "a", "b": "b", "c": "c"})
t.Assert(m.Map(), map[string]string{"a": "a", "b": "b", "c": "c"})
m.Removes([]string{"a", "b"})
t.Assert(m.Map(), map[string]string{"c": "c"})
})
}
func Test_StrStrMap_Iterator(t *testing.T) {
expect := map[string]string{"a": "a", "b": "b"}
m := gmap.NewStrStrMapFrom(expect)
m.Iterator(func(k string, v string) bool {
gtest.Assert(expect[k], v)
return true
gtest.C(t, func(t *gtest.T) {
expect := map[string]string{"a": "a", "b": "b"}
m := gmap.NewStrStrMapFrom(expect)
m.Iterator(func(k string, v string) bool {
t.Assert(expect[k], v)
return true
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k string, v string) bool {
i++
return true
})
m.Iterator(func(k string, v string) bool {
j++
return false
})
t.Assert(i, 2)
t.Assert(j, 1)
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k string, v string) bool {
i++
return true
})
m.Iterator(func(k string, v string) bool {
j++
return false
})
gtest.Assert(i, 2)
gtest.Assert(j, 1)
}
func Test_StrStrMap_Lock(t *testing.T) {
expect := map[string]string{"a": "a", "b": "b"}
gtest.C(t, func(t *gtest.T) {
expect := map[string]string{"a": "a", "b": "b"}
m := gmap.NewStrStrMapFrom(expect)
m.LockFunc(func(m map[string]string) {
gtest.Assert(m, expect)
})
m.RLockFunc(func(m map[string]string) {
gtest.Assert(m, expect)
m := gmap.NewStrStrMapFrom(expect)
m.LockFunc(func(m map[string]string) {
t.Assert(m, expect)
})
m.RLockFunc(func(m map[string]string) {
t.Assert(m, expect)
})
})
}
func Test_StrStrMap_Clone(t *testing.T) {
//clone 方法是深克隆
m := gmap.NewStrStrMapFrom(map[string]string{"a": "a", "b": "b", "c": "c"})
gtest.C(t, func(t *gtest.T) {
//clone 方法是深克隆
m := gmap.NewStrStrMapFrom(map[string]string{"a": "a", "b": "b", "c": "c"})
m_clone := m.Clone()
m.Remove("a")
//修改原 map,clone 后的 map 不影响
gtest.AssertIN("a", m_clone.Keys())
m_clone := m.Clone()
m.Remove("a")
//修改原 map,clone 后的 map 不影响
t.AssertIN("a", m_clone.Keys())
m_clone.Remove("b")
//修改clone map,原 map 不影响
gtest.AssertIN("b", m.Keys())
m_clone.Remove("b")
//修改clone map,原 map 不影响
t.AssertIN("b", m.Keys())
})
}
func Test_StrStrMap_Merge(t *testing.T) {
m1 := gmap.NewStrStrMap()
m2 := gmap.NewStrStrMap()
m1.Set("a", "a")
m2.Set("b", "b")
m1.Merge(m2)
gtest.Assert(m1.Map(), map[string]string{"a": "a", "b": "b"})
gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewStrStrMap()
m2 := gmap.NewStrStrMap()
m1.Set("a", "a")
m2.Set("b", "b")
m1.Merge(m2)
t.Assert(m1.Map(), map[string]string{"a": "a", "b": "b"})
})
}
func Test_StrStrMap_Map(t *testing.T) {
m := gmap.NewStrStrMap()
m.Set("1", "1")
m.Set("2", "2")
gtest.Assert(m.Get("1"), "1")
gtest.Assert(m.Get("2"), "2")
data := m.Map()
gtest.Assert(data["1"], "1")
gtest.Assert(data["2"], "2")
data["3"] = "3"
gtest.Assert(m.Get("3"), "3")
m.Set("4", "4")
gtest.Assert(data["4"], "4")
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrStrMap()
m.Set("1", "1")
m.Set("2", "2")
t.Assert(m.Get("1"), "1")
t.Assert(m.Get("2"), "2")
data := m.Map()
t.Assert(data["1"], "1")
t.Assert(data["2"], "2")
data["3"] = "3"
t.Assert(m.Get("3"), "3")
m.Set("4", "4")
t.Assert(data["4"], "4")
})
}
func Test_StrStrMap_MapCopy(t *testing.T) {
m := gmap.NewStrStrMap()
m.Set("1", "1")
m.Set("2", "2")
gtest.Assert(m.Get("1"), "1")
gtest.Assert(m.Get("2"), "2")
data := m.MapCopy()
gtest.Assert(data["1"], "1")
gtest.Assert(data["2"], "2")
data["3"] = "3"
gtest.Assert(m.Get("3"), "")
m.Set("4", "4")
gtest.Assert(data["4"], "")
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrStrMap()
m.Set("1", "1")
m.Set("2", "2")
t.Assert(m.Get("1"), "1")
t.Assert(m.Get("2"), "2")
data := m.MapCopy()
t.Assert(data["1"], "1")
t.Assert(data["2"], "2")
data["3"] = "3"
t.Assert(m.Get("3"), "")
m.Set("4", "4")
t.Assert(data["4"], "")
})
}
func Test_StrStrMap_FilterEmpty(t *testing.T) {
m := gmap.NewStrStrMap()
m.Set("1", "")
m.Set("2", "2")
gtest.Assert(m.Size(), 2)
gtest.Assert(m.Get("1"), "")
gtest.Assert(m.Get("2"), "2")
m.FilterEmpty()
gtest.Assert(m.Size(), 1)
gtest.Assert(m.Get("2"), "2")
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrStrMap()
m.Set("1", "")
m.Set("2", "2")
t.Assert(m.Size(), 2)
t.Assert(m.Get("1"), "")
t.Assert(m.Get("2"), "2")
m.FilterEmpty()
t.Assert(m.Size(), 1)
t.Assert(m.Get("2"), "2")
})
}
func Test_StrStrMap_Json(t *testing.T) {
// Marshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapStrStr{
"k1": "v1",
"k2": "v2",
@ -184,125 +201,125 @@ func Test_StrStrMap_Json(t *testing.T) {
m1 := gmap.NewStrStrMapFrom(data)
b1, err1 := json.Marshal(m1)
b2, err2 := json.Marshal(data)
gtest.Assert(err1, err2)
gtest.Assert(b1, b2)
t.Assert(err1, err2)
t.Assert(b1, b2)
})
// Unmarshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapStrStr{
"k1": "v1",
"k2": "v2",
}
b, err := json.Marshal(data)
gtest.Assert(err, nil)
t.Assert(err, nil)
m := gmap.NewStrStrMap()
err = json.Unmarshal(b, m)
gtest.Assert(err, nil)
gtest.Assert(m.Get("k1"), data["k1"])
gtest.Assert(m.Get("k2"), data["k2"])
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapStrStr{
"k1": "v1",
"k2": "v2",
}
b, err := json.Marshal(data)
gtest.Assert(err, nil)
t.Assert(err, nil)
var m gmap.StrStrMap
err = json.Unmarshal(b, &m)
gtest.Assert(err, nil)
gtest.Assert(m.Get("k1"), data["k1"])
gtest.Assert(m.Get("k2"), data["k2"])
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
})
}
func Test_StrStrMap_Pop(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrStrMapFrom(g.MapStrStr{
"k1": "v1",
"k2": "v2",
})
gtest.Assert(m.Size(), 2)
t.Assert(m.Size(), 2)
k1, v1 := m.Pop()
gtest.AssertIN(k1, g.Slice{"k1", "k2"})
gtest.AssertIN(v1, g.Slice{"v1", "v2"})
gtest.Assert(m.Size(), 1)
t.AssertIN(k1, g.Slice{"k1", "k2"})
t.AssertIN(v1, g.Slice{"v1", "v2"})
t.Assert(m.Size(), 1)
k2, v2 := m.Pop()
gtest.AssertIN(k2, g.Slice{"k1", "k2"})
gtest.AssertIN(v2, g.Slice{"v1", "v2"})
gtest.Assert(m.Size(), 0)
t.AssertIN(k2, g.Slice{"k1", "k2"})
t.AssertIN(v2, g.Slice{"v1", "v2"})
t.Assert(m.Size(), 0)
gtest.AssertNE(k1, k2)
gtest.AssertNE(v1, v2)
t.AssertNE(k1, k2)
t.AssertNE(v1, v2)
})
}
func Test_StrStrMap_Pops(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewStrStrMapFrom(g.MapStrStr{
"k1": "v1",
"k2": "v2",
"k3": "v3",
})
gtest.Assert(m.Size(), 3)
t.Assert(m.Size(), 3)
kArray := garray.New()
vArray := garray.New()
for k, v := range m.Pops(1) {
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
t.AssertIN(k, g.Slice{"k1", "k2", "k3"})
t.AssertIN(v, g.Slice{"v1", "v2", "v3"})
kArray.Append(k)
vArray.Append(v)
}
gtest.Assert(m.Size(), 2)
t.Assert(m.Size(), 2)
for k, v := range m.Pops(2) {
gtest.AssertIN(k, g.Slice{"k1", "k2", "k3"})
gtest.AssertIN(v, g.Slice{"v1", "v2", "v3"})
t.AssertIN(k, g.Slice{"k1", "k2", "k3"})
t.AssertIN(v, g.Slice{"v1", "v2", "v3"})
kArray.Append(k)
vArray.Append(v)
}
gtest.Assert(m.Size(), 0)
t.Assert(m.Size(), 0)
gtest.Assert(kArray.Unique().Len(), 3)
gtest.Assert(vArray.Unique().Len(), 3)
t.Assert(kArray.Unique().Len(), 3)
t.Assert(vArray.Unique().Len(), 3)
})
}
func TestStrStrMap_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Map *gmap.StrStrMap
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"k1":"v1","k2":"v2"}`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get("k1"), "v1")
gtest.Assert(t.Map.Get("k2"), "v2")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get("k1"), "v1")
t.Assert(v.Map.Get("k2"), "v2")
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.Map{
"k1": "v1",
"k2": "v2",
},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get("k1"), "v1")
gtest.Assert(t.Map.Get("k2"), "v2")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get("k1"), "v1")
t.Assert(v.Map.Get("k2"), "v2")
})
}

View File

@ -18,96 +18,122 @@ import (
)
func Test_TreeMap_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewTreeMap(gutil.ComparatorString)
m.Set("key1", "val1")
gtest.Assert(m.Keys(), []interface{}{"key1"})
t.Assert(m.Keys(), []interface{}{"key1"})
gtest.Assert(m.Get("key1"), "val1")
gtest.Assert(m.Size(), 1)
gtest.Assert(m.IsEmpty(), false)
t.Assert(m.Get("key1"), "val1")
t.Assert(m.Size(), 1)
t.Assert(m.IsEmpty(), false)
gtest.Assert(m.GetOrSet("key2", "val2"), "val2")
gtest.Assert(m.SetIfNotExist("key2", "val2"), false)
t.Assert(m.GetOrSet("key2", "val2"), "val2")
t.Assert(m.SetIfNotExist("key2", "val2"), false)
gtest.Assert(m.SetIfNotExist("key3", "val3"), true)
t.Assert(m.SetIfNotExist("key3", "val3"), true)
gtest.Assert(m.Remove("key2"), "val2")
gtest.Assert(m.Contains("key2"), false)
t.Assert(m.Remove("key2"), "val2")
t.Assert(m.Contains("key2"), false)
gtest.AssertIN("key3", m.Keys())
gtest.AssertIN("key1", m.Keys())
gtest.AssertIN("val3", m.Values())
gtest.AssertIN("val1", m.Values())
t.AssertIN("key3", m.Keys())
t.AssertIN("key1", m.Keys())
t.AssertIN("val3", m.Values())
t.AssertIN("val1", m.Values())
m.Flip()
gtest.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val1": "key1"})
t.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val1": "key1"})
m.Clear()
gtest.Assert(m.Size(), 0)
gtest.Assert(m.IsEmpty(), true)
t.Assert(m.Size(), 0)
t.Assert(m.IsEmpty(), true)
m2 := gmap.NewTreeMapFrom(gutil.ComparatorString, map[interface{}]interface{}{1: 1, "key1": "val1"})
gtest.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"})
t.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"})
})
}
func Test_TreeMap_Set_Fun(t *testing.T) {
m := gmap.NewTreeMap(gutil.ComparatorString)
m.GetOrSetFunc("fun", getValue)
m.GetOrSetFuncLock("funlock", getValue)
gtest.Assert(m.Get("funlock"), 3)
gtest.Assert(m.Get("fun"), 3)
m.GetOrSetFunc("fun", getValue)
gtest.Assert(m.SetIfNotExistFunc("fun", getValue), false)
gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false)
gtest.C(t, func(t *gtest.T) {
m := gmap.NewTreeMap(gutil.ComparatorString)
m.GetOrSetFunc("fun", getValue)
m.GetOrSetFuncLock("funlock", getValue)
t.Assert(m.Get("funlock"), 3)
t.Assert(m.Get("fun"), 3)
m.GetOrSetFunc("fun", getValue)
t.Assert(m.SetIfNotExistFunc("fun", getValue), false)
t.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false)
})
}
func Test_TreeMap_Batch(t *testing.T) {
m := gmap.NewTreeMap(gutil.ComparatorString)
m.Sets(map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
gtest.Assert(m.Map(), map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
m.Removes([]interface{}{"key1", 1})
gtest.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"})
gtest.C(t, func(t *gtest.T) {
m := gmap.NewTreeMap(gutil.ComparatorString)
m.Sets(map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
t.Assert(m.Map(), map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
m.Removes([]interface{}{"key1", 1})
t.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"})
})
}
func Test_TreeMap_Iterator(t *testing.T) {
expect := map[interface{}]interface{}{1: 1, "key1": "val1"}
gtest.C(t, func(t *gtest.T) {
expect := map[interface{}]interface{}{1: 1, "key1": "val1"}
m := gmap.NewTreeMapFrom(gutil.ComparatorString, expect)
m.Iterator(func(k interface{}, v interface{}) bool {
t.Assert(expect[k], v)
return true
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k interface{}, v interface{}) bool {
i++
return true
})
m.Iterator(func(k interface{}, v interface{}) bool {
j++
return false
})
t.Assert(i, 2)
t.Assert(j, 1)
})
m := gmap.NewTreeMapFrom(gutil.ComparatorString, expect)
m.Iterator(func(k interface{}, v interface{}) bool {
gtest.Assert(expect[k], v)
return true
gtest.C(t, func(t *gtest.T) {
expect := map[interface{}]interface{}{1: 1, "key1": "val1"}
m := gmap.NewTreeMapFrom(gutil.ComparatorString, expect)
for i := 0; i < 10; i++ {
m.IteratorAsc(func(k interface{}, v interface{}) bool {
t.Assert(expect[k], v)
return true
})
}
j := 0
for i := 0; i < 10; i++ {
m.IteratorAsc(func(k interface{}, v interface{}) bool {
j++
return false
})
}
t.Assert(j, 10)
})
// 断言返回值对遍历控制
i := 0
j := 0
m.Iterator(func(k interface{}, v interface{}) bool {
i++
return true
})
m.Iterator(func(k interface{}, v interface{}) bool {
j++
return false
})
gtest.Assert(i, 2)
gtest.Assert(j, 1)
}
func Test_TreeMap_Clone(t *testing.T) {
//clone 方法是深克隆
m := gmap.NewTreeMapFrom(gutil.ComparatorString, map[interface{}]interface{}{1: 1, "key1": "val1"})
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
gtest.AssertIN(1, m_clone.Keys())
gtest.C(t, func(t *gtest.T) {
//clone 方法是深克隆
m := gmap.NewTreeMapFrom(gutil.ComparatorString, map[interface{}]interface{}{1: 1, "key1": "val1"})
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
t.AssertIN(1, m_clone.Keys())
m_clone.Remove("key1")
//修改clone map,原 map 不影响
gtest.AssertIN("key1", m.Keys())
m_clone.Remove("key1")
//修改clone map,原 map 不影响
t.AssertIN("key1", m.Keys())
})
}
func Test_TreeMap_Json(t *testing.T) {
// Marshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapAnyAny{
"k1": "v1",
"k2": "v2",
@ -115,72 +141,72 @@ func Test_TreeMap_Json(t *testing.T) {
m1 := gmap.NewTreeMapFrom(gutil.ComparatorString, data)
b1, err1 := json.Marshal(m1)
b2, err2 := json.Marshal(gconv.Map(data))
gtest.Assert(err1, err2)
gtest.Assert(b1, b2)
t.Assert(err1, err2)
t.Assert(b1, b2)
})
// Unmarshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapAnyAny{
"k1": "v1",
"k2": "v2",
}
b, err := json.Marshal(gconv.Map(data))
gtest.Assert(err, nil)
t.Assert(err, nil)
m := gmap.NewTreeMap(gutil.ComparatorString)
err = json.Unmarshal(b, m)
gtest.Assert(err, nil)
gtest.Assert(m.Get("k1"), data["k1"])
gtest.Assert(m.Get("k2"), data["k2"])
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data := g.MapAnyAny{
"k1": "v1",
"k2": "v2",
}
b, err := json.Marshal(gconv.Map(data))
gtest.Assert(err, nil)
t.Assert(err, nil)
var m gmap.TreeMap
err = json.Unmarshal(b, &m)
gtest.Assert(err, nil)
gtest.Assert(m.Get("k1"), data["k1"])
gtest.Assert(m.Get("k2"), data["k2"])
t.Assert(err, nil)
t.Assert(m.Get("k1"), data["k1"])
t.Assert(m.Get("k2"), data["k2"])
})
}
func TestTreeMap_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Map *gmap.TreeMap
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"k1":"v1","k2":"v2"}`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get("k1"), "v1")
gtest.Assert(t.Map.Get("k2"), "v2")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get("k1"), "v1")
t.Assert(v.Map.Get("k2"), "v2")
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.Map{
"k1": "v1",
"k2": "v2",
},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Map.Size(), 2)
gtest.Assert(t.Map.Get("k1"), "v1")
gtest.Assert(t.Map.Get("k2"), "v2")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Map.Size(), 2)
t.Assert(v.Map.Get("k1"), "v1")
t.Assert(v.Map.Get("k2"), "v2")
})
}

View File

@ -17,22 +17,31 @@ import (
"github.com/gogf/gf/os/gtimer"
)
// Object-Reusable Pool.
// Pool is an Object-Reusable Pool.
type Pool struct {
list *glist.List // Available/idle list.
closed *gtype.Bool // Whether the pool is closed.
Expire int64 // Max idle time(ms), after which it is recycled.
NewFunc func() (interface{}, error) // Callback function to create item.
ExpireFunc func(interface{}) // Expired destruction function for objects.
// This function needs to be defined when the pool object
// needs to perform additional destruction operations.
// Available/idle items list.
list *glist.List
// Whether the pool is closed.
closed *gtype.Bool
// Time To Live for pool items.
TTL time.Duration
// Callback function to create pool item.
NewFunc func() (interface{}, error)
// ExpireFunc is the for expired items destruction.
// This function needs to be defined when the pool items
// need to perform additional destruction operations.
// Eg: net.Conn, os.File, etc.
ExpireFunc func(interface{})
}
// Pool item.
type poolItem struct {
expire int64 // Expire time(millisecond).
value interface{} // Value.
expire int64 // Expire timestamp in milliseconds.
value interface{} // Item value.
}
// Creation function for object.
@ -41,47 +50,64 @@ type NewFunc func() (interface{}, error)
// Destruction function for object.
type ExpireFunc func(interface{})
// New returns a new object pool.
// New creates and returns a new object pool.
// To ensure execution efficiency, the expiration time cannot be modified once it is set.
//
// Expiration logic:
// expire = 0 : not expired;
// expire < 0 : immediate expired after use;
// expire > 0 : timeout expired;
// Note that the expiration time unit is ** milliseconds **.
func New(expire int, newFunc NewFunc, expireFunc ...ExpireFunc) *Pool {
// Note the expiration logic:
// ttl = 0 : not expired;
// ttl < 0 : immediate expired after use;
// ttl > 0 : timeout expired;
func New(ttl time.Duration, newFunc NewFunc, expireFunc ...ExpireFunc) *Pool {
r := &Pool{
list: glist.New(true),
closed: gtype.NewBool(),
Expire: int64(expire),
TTL: ttl,
NewFunc: newFunc,
}
if len(expireFunc) > 0 {
r.ExpireFunc = expireFunc[0]
}
gtimer.AddSingleton(time.Second, r.checkExpire)
gtimer.AddSingleton(time.Second, r.checkExpireItems)
return r
}
// Put puts an item to pool.
func (p *Pool) Put(value interface{}) {
func (p *Pool) Put(value interface{}) error {
if p.closed.Val() {
return errors.New("pool is closed")
}
item := &poolItem{
value: value,
}
if p.Expire == 0 {
if p.TTL == 0 {
item.expire = 0
} else {
item.expire = gtime.TimestampMilli() + p.Expire
// As for Golang version < 1.13, there's no method Milliseconds for time.Duration.
// So we need calculate the milliseconds using its nanoseconds value.
item.expire = gtime.TimestampMilli() + p.TTL.Nanoseconds()/1000000
}
p.list.PushBack(item)
return nil
}
// Clear clears pool, which means it will remove all items from pool.
func (p *Pool) Clear() {
p.list.RemoveAll()
if p.ExpireFunc != nil {
for {
if r := p.list.PopFront(); r != nil {
p.ExpireFunc(r.(*poolItem).value)
} else {
break
}
}
} else {
p.list.RemoveAll()
}
}
// Get picks an item from pool.
// Get picks and returns an item from pool. If the pool is empty and NewFunc is defined,
// it creates and returns one from NewFunc.
func (p *Pool) Get() (interface{}, error) {
for !p.closed.Val() {
if r := p.list.PopFront(); r != nil {
@ -106,12 +132,13 @@ func (p *Pool) Size() int {
// Close closes the pool. If <p> has ExpireFunc,
// then it automatically closes all items using this function before it's closed.
// Commonly you do not need call this function manually.
func (p *Pool) Close() {
p.closed.Set(true)
}
// checkExpire removes expired items from pool every second.
func (p *Pool) checkExpire() {
// checkExpire removes expired items from pool in every second.
func (p *Pool) checkExpireItems() {
if p.closed.Val() {
// If p has ExpireFunc,
// then it must close all items using this function.
@ -126,11 +153,24 @@ func (p *Pool) checkExpire() {
}
gtimer.Exit()
}
// All items do not expire.
if p.TTL == 0 {
return
}
// The latest item expire timestamp in milliseconds.
var latestExpire int64 = -1
// Retrieve the current timestamp in milliseconds, it expires the items
// by comparing with this timestamp. It is not accurate comparison for
// every items expired, but high performance.
var timestampMilli = gtime.TimestampMilli()
for {
// TODO Do not use Pop and Push mechanism, which is not graceful.
if latestExpire > timestampMilli {
break
}
if r := p.list.PopFront(); r != nil {
item := r.(*poolItem)
if item.expire == 0 || item.expire > gtime.TimestampMilli() {
latestExpire = item.expire
if item.expire > timestampMilli {
p.list.PushFront(item)
break
}

View File

@ -11,11 +11,12 @@ package gpool_test
import (
"sync"
"testing"
"time"
"github.com/gogf/gf/container/gpool"
)
var pool = gpool.New(99999999, nil)
var pool = gpool.New(time.Hour, nil)
var syncp = sync.Pool{}
func BenchmarkGPoolPut(b *testing.B) {

View File

@ -28,7 +28,7 @@ var ef gpool.ExpireFunc = func(i interface{}) {
}
func Test_Gpool(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
//
//expire = 0
p1 := gpool.New(0, nf)
@ -37,63 +37,63 @@ func Test_Gpool(t *testing.T) {
time.Sleep(1 * time.Second)
//test won't be timeout
v1, err1 := p1.Get()
gtest.Assert(err1, nil)
gtest.AssertIN(v1, g.Slice{1, 2})
t.Assert(err1, nil)
t.AssertIN(v1, g.Slice{1, 2})
//test clear
p1.Clear()
gtest.Assert(p1.Size(), 0)
t.Assert(p1.Size(), 0)
//test newFunc
v1, err1 = p1.Get()
gtest.Assert(err1, nil)
gtest.Assert(v1, "hello")
t.Assert(err1, nil)
t.Assert(v1, "hello")
//put data again
p1.Put(3)
p1.Put(4)
v1, err1 = p1.Get()
gtest.Assert(err1, nil)
gtest.AssertIN(v1, g.Slice{3, 4})
t.Assert(err1, nil)
t.AssertIN(v1, g.Slice{3, 4})
//test close
p1.Close()
v1, err1 = p1.Get()
gtest.Assert(err1, nil)
gtest.Assert(v1, "hello")
t.Assert(err1, nil)
t.Assert(v1, "hello")
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
//
//expire > 0
p2 := gpool.New(2000, nil, ef)
p2 := gpool.New(2*time.Second, nil, ef)
for index := 0; index < 10; index++ {
p2.Put(index)
}
gtest.Assert(p2.Size(), 10)
t.Assert(p2.Size(), 10)
v2, err2 := p2.Get()
gtest.Assert(err2, nil)
gtest.Assert(v2, 0)
t.Assert(err2, nil)
t.Assert(v2, 0)
//test timeout expireFunc
time.Sleep(3 * time.Second)
v2, err2 = p2.Get()
gtest.Assert(err2, errors.New("pool is empty"))
gtest.Assert(v2, nil)
t.Assert(err2, errors.New("pool is empty"))
t.Assert(v2, nil)
//test close expireFunc
for index := 0; index < 10; index++ {
p2.Put(index)
}
gtest.Assert(p2.Size(), 10)
t.Assert(p2.Size(), 10)
v2, err2 = p2.Get()
gtest.Assert(err2, nil)
gtest.Assert(v2, 0)
t.Assert(err2, nil)
t.Assert(v2, 0)
assertIndex = 0
p2.Close()
time.Sleep(3 * time.Second)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
//
//expire < 0
p3 := gpool.New(-1, nil)
v3, err3 := p3.Get()
gtest.Assert(err3, errors.New("pool is empty"))
gtest.Assert(v3, nil)
t.Assert(err3, errors.New("pool is empty"))
t.Assert(v3, nil)
})
}

View File

@ -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 gqueue provides a dynamic/static concurrent-safe queue.
// Package gqueue provides dynamic/static concurrent-safe queue.
//
// Features:
//
@ -25,6 +25,7 @@ import (
"github.com/gogf/gf/container/gtype"
)
// Queue is a concurrent-safe queue built on doubly linked list and channel.
type Queue struct {
limit int // Limit for queue size.
list *glist.List // Underlying list structure for data maintaining.
@ -54,14 +55,14 @@ func New(limit ...int) *Queue {
q.list = glist.New(true)
q.events = make(chan struct{}, math.MaxInt32)
q.C = make(chan interface{}, gDEFAULT_QUEUE_SIZE)
go q.startAsyncLoop()
go q.asyncLoopFromListToChannel()
}
return q
}
// startAsyncLoop starts an asynchronous goroutine,
// asyncLoopFromListToChannel starts an asynchronous goroutine,
// which handles the data synchronization from list <q.list> to channel <q.C>.
func (q *Queue) startAsyncLoop() {
func (q *Queue) asyncLoopFromListToChannel() {
defer func() {
if q.closed.Val() {
_ = recover()

View File

@ -17,41 +17,49 @@ import (
)
func TestQueue_Len(t *testing.T) {
max := 100
for n := 10; n < max; n++ {
q1 := gqueue.New(max)
for i := 0; i < max; i++ {
q1.Push(i)
gtest.C(t, func(t *gtest.T) {
max := 100
for n := 10; n < max; n++ {
q1 := gqueue.New(max)
for i := 0; i < max; i++ {
q1.Push(i)
}
t.Assert(q1.Len(), max)
t.Assert(q1.Size(), max)
}
gtest.Assert(q1.Len(), max)
gtest.Assert(q1.Size(), max)
}
})
}
func TestQueue_Basic(t *testing.T) {
q := gqueue.New()
for i := 0; i < 100; i++ {
q.Push(i)
}
gtest.Assert(q.Pop(), 0)
gtest.Assert(q.Pop(), 1)
gtest.C(t, func(t *gtest.T) {
q := gqueue.New()
for i := 0; i < 100; i++ {
q.Push(i)
}
t.Assert(q.Pop(), 0)
t.Assert(q.Pop(), 1)
})
}
func TestQueue_Pop(t *testing.T) {
q1 := gqueue.New()
q1.Push(1)
q1.Push(2)
q1.Push(3)
q1.Push(4)
i1 := q1.Pop()
gtest.Assert(i1, 1)
gtest.C(t, func(t *gtest.T) {
q1 := gqueue.New()
q1.Push(1)
q1.Push(2)
q1.Push(3)
q1.Push(4)
i1 := q1.Pop()
t.Assert(i1, 1)
})
}
func TestQueue_Close(t *testing.T) {
q1 := gqueue.New()
q1.Push(1)
q1.Push(2)
time.Sleep(time.Millisecond)
gtest.Assert(q1.Len(), 2)
q1.Close()
gtest.C(t, func(t *gtest.T) {
q1 := gqueue.New()
q1.Push(1)
q1.Push(2)
time.Sleep(time.Millisecond)
t.Assert(q1.Len(), 2)
q1.Close()
})
}

View File

@ -16,7 +16,7 @@ type Student struct {
}
func TestRing_Val(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
//定义cap 为3的ring类型数据
r := gring.New(3, true)
//分别给3个元素初始化赋值
@ -25,46 +25,46 @@ func TestRing_Val(t *testing.T) {
r.Put(&Student{3, "alon", false})
//元素取值并判断和预设值是否相等
gtest.Assert(r.Val().(*Student).name, "jimmy")
t.Assert(r.Val().(*Student).name, "jimmy")
//从当前位置往后移两个元素
r.Move(2)
gtest.Assert(r.Val().(*Student).name, "alon")
t.Assert(r.Val().(*Student).name, "alon")
//更新元素值
//测试 value == nil
r.Set(nil)
gtest.Assert(r.Val(), nil)
t.Assert(r.Val(), nil)
//测试value != nil
r.Set(&Student{3, "jack", true})
})
}
func TestRing_CapLen(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
r := gring.New(10)
r.Put("goframe")
//cap长度 10
gtest.Assert(r.Cap(), 10)
t.Assert(r.Cap(), 10)
//已有数据项 1
gtest.Assert(r.Len(), 1)
t.Assert(r.Len(), 1)
})
}
func TestRing_Position(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
r := gring.New(2)
r.Put(1)
r.Put(2)
//往后移动1个元素
r.Next()
gtest.Assert(r.Val(), 2)
t.Assert(r.Val(), 2)
//往前移动1个元素
r.Prev()
gtest.Assert(r.Val(), 1)
t.Assert(r.Val(), 1)
})
}
func TestRing_Link(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
r := gring.New(3)
r.Put(1)
r.Put(2)
@ -74,13 +74,13 @@ func TestRing_Link(t *testing.T) {
s.Put("b")
rs := r.Link(s)
gtest.Assert(rs.Move(2).Val(), "b")
t.Assert(rs.Move(2).Val(), "b")
})
}
func TestRing_Unlink(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
r := gring.New(5)
for i := 0; i < 5; i++ {
r.Put(i + 1)
@ -89,13 +89,13 @@ func TestRing_Unlink(t *testing.T) {
// 删除当前位置往后的2个数据返回被删除的数据
// 重新计算s len
s := r.Unlink(2) // 2 3
gtest.Assert(s.Val(), 2)
gtest.Assert(s.Len(), 1)
t.Assert(s.Val(), 2)
t.Assert(s.Len(), 1)
})
}
func TestRing_Slice(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
ringLen := 5
r := gring.New(ringLen)
for i := 0; i < ringLen; i++ {
@ -103,49 +103,49 @@ func TestRing_Slice(t *testing.T) {
}
r.Move(2) // 3
array := r.SliceNext() // [3 4 5 1 2]
gtest.Assert(array[0], 3)
gtest.Assert(len(array), 5)
t.Assert(array[0], 3)
t.Assert(len(array), 5)
//判断array是否等于[3 4 5 1 2]
ra := []int{3, 4, 5, 1, 2}
gtest.Assert(ra, array)
t.Assert(ra, array)
//第3个元素设为nil
r.Set(nil)
array2 := r.SliceNext() //[4 5 1 2]
//返回当前位置往后不为空的元素数组长度为4
gtest.Assert(array2, g.Slice{4, 5, 1, 2})
t.Assert(array2, g.Slice{4, 5, 1, 2})
array3 := r.SlicePrev() //[2 1 5 4]
gtest.Assert(array3, g.Slice{2, 1, 5, 4})
t.Assert(array3, g.Slice{2, 1, 5, 4})
s := gring.New(ringLen)
for i := 0; i < ringLen; i++ {
s.Put(i + 1)
}
array4 := s.SlicePrev() // []
gtest.Assert(array4, g.Slice{1, 5, 4, 3, 2})
t.Assert(array4, g.Slice{1, 5, 4, 3, 2})
})
}
func TestRing_RLockIterator(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
ringLen := 5
r := gring.New(ringLen)
//ring不存在有值元素
r.RLockIteratorNext(func(v interface{}) bool {
gtest.Assert(v, nil)
t.Assert(v, nil)
return false
})
r.RLockIteratorNext(func(v interface{}) bool {
gtest.Assert(v, nil)
t.Assert(v, nil)
return true
})
r.RLockIteratorPrev(func(v interface{}) bool {
gtest.Assert(v, nil)
t.Assert(v, nil)
return true
})
@ -156,14 +156,14 @@ func TestRing_RLockIterator(t *testing.T) {
//回调函数返回true,RLockIteratorNext遍历5次,期望值分别是1、2、3、4、5
i := 0
r.RLockIteratorNext(func(v interface{}) bool {
gtest.Assert(v, i+1)
t.Assert(v, i+1)
i++
return true
})
//RLockIteratorPrev遍历1次返回 false,退出遍历
r.RLockIteratorPrev(func(v interface{}) bool {
gtest.Assert(v, 1)
t.Assert(v, 1)
return false
})
@ -171,30 +171,30 @@ func TestRing_RLockIterator(t *testing.T) {
}
func TestRing_LockIterator(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
ringLen := 5
r := gring.New(ringLen)
//不存在有值元素
r.LockIteratorNext(func(item *ring.Ring) bool {
gtest.Assert(item.Value, nil)
t.Assert(item.Value, nil)
return false
})
r.LockIteratorNext(func(item *ring.Ring) bool {
gtest.Assert(item.Value, nil)
t.Assert(item.Value, nil)
return false
})
r.LockIteratorNext(func(item *ring.Ring) bool {
gtest.Assert(item.Value, nil)
t.Assert(item.Value, nil)
return true
})
r.LockIteratorPrev(func(item *ring.Ring) bool {
gtest.Assert(item.Value, nil)
t.Assert(item.Value, nil)
return false
})
r.LockIteratorPrev(func(item *ring.Ring) bool {
gtest.Assert(item.Value, nil)
t.Assert(item.Value, nil)
return true
})
@ -208,7 +208,7 @@ func TestRing_LockIterator(t *testing.T) {
ii := 0
r.LockIteratorNext(func(item *ring.Ring) bool {
//校验每一次遍历取值是否是期望值
gtest.Assert(item.Value, array1[ii])
t.Assert(item.Value, array1[ii])
ii++
return true
})
@ -221,7 +221,7 @@ func TestRing_LockIterator(t *testing.T) {
if i > 2 {
return false
}
gtest.Assert(item.Value, a[i])
t.Assert(item.Value, a[i])
i++
return true
})

View File

@ -22,50 +22,50 @@ import (
)
func TestSet_New(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
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)
t.Assert(s.Size(), 4)
t.AssertIN(1, s.Slice())
t.AssertIN(2, s.Slice())
t.AssertIN(3, s.Slice())
t.AssertIN(4, s.Slice())
t.AssertNI(0, s.Slice())
t.Assert(s.Contains(4), true)
t.Assert(s.Contains(5), false)
s.Remove(1)
gtest.Assert(s.Size(), 3)
t.Assert(s.Size(), 3)
s.Clear()
gtest.Assert(s.Size(), 0)
t.Assert(s.Size(), 0)
})
}
func TestSet_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
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)
t.Assert(s.Size(), 4)
t.AssertIN(1, s.Slice())
t.AssertIN(2, s.Slice())
t.AssertIN(3, s.Slice())
t.AssertIN(4, s.Slice())
t.AssertNI(0, s.Slice())
t.Assert(s.Contains(4), true)
t.Assert(s.Contains(5), false)
s.Remove(1)
gtest.Assert(s.Size(), 3)
t.Assert(s.Size(), 3)
s.Clear()
gtest.Assert(s.Size(), 0)
t.Assert(s.Size(), 0)
})
}
func TestSet_Iterator(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.NewSet()
s.Add(1).Add(2).Add(3)
gtest.Assert(s.Size(), 3)
t.Assert(s.Size(), 3)
a1 := garray.New(true)
a2 := garray.New(true)
@ -77,22 +77,22 @@ func TestSet_Iterator(t *testing.T) {
a2.Append(1)
return true
})
gtest.Assert(a1.Len(), 1)
gtest.Assert(a2.Len(), 3)
t.Assert(a1.Len(), 1)
t.Assert(a2.Len(), 3)
})
}
func TestSet_LockFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.NewSet()
s.Add(1).Add(2).Add(3)
gtest.Assert(s.Size(), 3)
t.Assert(s.Size(), 3)
s.LockFunc(func(m map[interface{}]struct{}) {
delete(m, 1)
})
gtest.Assert(s.Size(), 2)
t.Assert(s.Size(), 2)
s.RLockFunc(func(m map[interface{}]struct{}) {
gtest.Assert(m, map[interface{}]struct{}{
t.Assert(m, map[interface{}]struct{}{
3: struct{}{},
2: struct{}{},
})
@ -101,302 +101,302 @@ func TestSet_LockFunc(t *testing.T) {
}
func TestSet_Equal(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
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)
t.Assert(s1.Equal(s2), true)
t.Assert(s1.Equal(s3), false)
})
}
func TestSet_IsSubsetOf(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
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)
t.Assert(s1.IsSubsetOf(s2), true)
t.Assert(s2.IsSubsetOf(s3), true)
t.Assert(s1.IsSubsetOf(s3), true)
t.Assert(s2.IsSubsetOf(s1), false)
t.Assert(s3.IsSubsetOf(s2), false)
})
}
func TestSet_Union(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
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)
t.Assert(s3.Contains(1), true)
t.Assert(s3.Contains(2), true)
t.Assert(s3.Contains(3), true)
t.Assert(s3.Contains(4), true)
})
}
func TestSet_Diff(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
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)
t.Assert(s3.Contains(1), true)
t.Assert(s3.Contains(2), true)
t.Assert(s3.Contains(3), false)
t.Assert(s3.Contains(4), false)
})
}
func TestSet_Intersect(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
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)
t.Assert(s3.Contains(1), false)
t.Assert(s3.Contains(2), false)
t.Assert(s3.Contains(3), true)
t.Assert(s3.Contains(4), false)
})
}
func TestSet_Complement(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
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)
t.Assert(s3.Contains(1), false)
t.Assert(s3.Contains(2), false)
t.Assert(s3.Contains(4), true)
t.Assert(s3.Contains(5), true)
})
}
func TestNewFrom(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewFrom("a")
s2 := gset.NewFrom("b", false)
s3 := gset.NewFrom(3, true)
s4 := gset.NewFrom([]string{"s1", "s2"}, true)
gtest.Assert(s1.Contains("a"), true)
gtest.Assert(s2.Contains("b"), true)
gtest.Assert(s3.Contains(3), true)
gtest.Assert(s4.Contains("s1"), true)
gtest.Assert(s4.Contains("s3"), false)
t.Assert(s1.Contains("a"), true)
t.Assert(s2.Contains("b"), true)
t.Assert(s3.Contains(3), true)
t.Assert(s4.Contains("s1"), true)
t.Assert(s4.Contains("s3"), false)
})
}
func TestNew(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.New()
s1.Add("a").Add(2)
s2 := gset.New(true)
s2.Add("b").Add(3)
gtest.Assert(s1.Contains("a"), true)
t.Assert(s1.Contains("a"), true)
})
}
func TestSet_Join(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.New(true)
s1.Add("a").Add("a1").Add("b").Add("c")
str1 := s1.Join(",")
gtest.Assert(strings.Contains(str1, "a1"), true)
t.Assert(strings.Contains(str1, "a1"), true)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.New(true)
s1.Add("a").Add(`"b"`).Add(`\c`)
str1 := s1.Join(",")
gtest.Assert(strings.Contains(str1, `"b"`), true)
gtest.Assert(strings.Contains(str1, `\c`), true)
gtest.Assert(strings.Contains(str1, `a`), true)
t.Assert(strings.Contains(str1, `"b"`), true)
t.Assert(strings.Contains(str1, `\c`), true)
t.Assert(strings.Contains(str1, `a`), true)
})
}
func TestSet_String(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.New(true)
s1.Add("a").Add("a2").Add("b").Add("c")
str1 := s1.String()
gtest.Assert(strings.Contains(str1, "["), true)
gtest.Assert(strings.Contains(str1, "]"), true)
gtest.Assert(strings.Contains(str1, "a2"), true)
t.Assert(strings.Contains(str1, "["), true)
t.Assert(strings.Contains(str1, "]"), true)
t.Assert(strings.Contains(str1, "a2"), true)
})
}
func TestSet_Merge(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.New(true)
s2 := gset.New(true)
s1.Add("a").Add("a2").Add("b").Add("c")
s2.Add("b").Add("b1").Add("e").Add("f")
ss := s1.Merge(s2)
gtest.Assert(ss.Contains("a2"), true)
gtest.Assert(ss.Contains("b1"), true)
t.Assert(ss.Contains("a2"), true)
t.Assert(ss.Contains("b1"), true)
})
}
func TestSet_Sum(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.New(true)
s1.Add(1).Add(2).Add(3).Add(4)
gtest.Assert(s1.Sum(), int(10))
t.Assert(s1.Sum(), int(10))
})
}
func TestSet_Pop(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.New(true)
s.Add(1).Add(2).Add(3).Add(4)
gtest.Assert(s.Size(), 4)
gtest.AssertIN(s.Pop(), []int{1, 2, 3, 4})
gtest.Assert(s.Size(), 3)
t.Assert(s.Size(), 4)
t.AssertIN(s.Pop(), []int{1, 2, 3, 4})
t.Assert(s.Size(), 3)
})
}
func TestSet_Pops(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.New(true)
s.Add(1).Add(2).Add(3).Add(4)
gtest.Assert(s.Size(), 4)
gtest.Assert(s.Pops(0), nil)
gtest.AssertIN(s.Pops(1), []int{1, 2, 3, 4})
gtest.Assert(s.Size(), 3)
t.Assert(s.Size(), 4)
t.Assert(s.Pops(0), nil)
t.AssertIN(s.Pops(1), []int{1, 2, 3, 4})
t.Assert(s.Size(), 3)
a := s.Pops(6)
gtest.Assert(len(a), 3)
gtest.AssertIN(a, []int{1, 2, 3, 4})
gtest.Assert(s.Size(), 0)
t.Assert(len(a), 3)
t.AssertIN(a, []int{1, 2, 3, 4})
t.Assert(s.Size(), 0)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.New(true)
a := []interface{}{1, 2, 3, 4}
s.Add(a...)
gtest.Assert(s.Size(), 4)
gtest.Assert(s.Pops(-2), nil)
gtest.AssertIN(s.Pops(-1), a)
t.Assert(s.Size(), 4)
t.Assert(s.Pops(-2), nil)
t.AssertIN(s.Pops(-1), a)
})
}
func TestSet_Json(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []interface{}{"a", "b", "d", "c"}
a1 := gset.NewFrom(s1)
b1, err1 := json.Marshal(a1)
b2, err2 := json.Marshal(s1)
gtest.Assert(len(b1), len(b2))
gtest.Assert(err1, err2)
t.Assert(len(b1), len(b2))
t.Assert(err1, err2)
a2 := gset.New()
err2 = json.Unmarshal(b2, &a2)
gtest.Assert(err2, nil)
gtest.Assert(a2.Contains("a"), true)
gtest.Assert(a2.Contains("b"), true)
gtest.Assert(a2.Contains("c"), true)
gtest.Assert(a2.Contains("d"), true)
gtest.Assert(a2.Contains("e"), false)
t.Assert(err2, nil)
t.Assert(a2.Contains("a"), true)
t.Assert(a2.Contains("b"), true)
t.Assert(a2.Contains("c"), true)
t.Assert(a2.Contains("d"), true)
t.Assert(a2.Contains("e"), false)
var a3 gset.Set
err := json.Unmarshal(b2, &a3)
gtest.Assert(err, nil)
gtest.Assert(a3.Contains("a"), true)
gtest.Assert(a3.Contains("b"), true)
gtest.Assert(a3.Contains("c"), true)
gtest.Assert(a3.Contains("d"), true)
gtest.Assert(a3.Contains("e"), false)
t.Assert(err, nil)
t.Assert(a3.Contains("a"), true)
t.Assert(a3.Contains("b"), true)
t.Assert(a3.Contains("c"), true)
t.Assert(a3.Contains("d"), true)
t.Assert(a3.Contains("e"), false)
})
}
func TestSet_AddIfNotExistFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.New(true)
s.Add(1)
gtest.Assert(s.Contains(1), true)
gtest.Assert(s.Contains(2), false)
t.Assert(s.Contains(1), true)
t.Assert(s.Contains(2), false)
s.AddIfNotExistFunc(2, func() interface{} {
return 3
})
gtest.Assert(s.Contains(2), false)
gtest.Assert(s.Contains(3), true)
t.Assert(s.Contains(2), false)
t.Assert(s.Contains(3), true)
s.AddIfNotExistFunc(3, func() interface{} {
return 4
})
gtest.Assert(s.Contains(3), true)
gtest.Assert(s.Contains(4), false)
t.Assert(s.Contains(3), true)
t.Assert(s.Contains(4), false)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.New(true)
s.Add(1)
gtest.Assert(s.Contains(1), true)
gtest.Assert(s.Contains(2), false)
t.Assert(s.Contains(1), true)
t.Assert(s.Contains(2), false)
s.AddIfNotExistFuncLock(2, func() interface{} {
return 3
})
gtest.Assert(s.Contains(2), false)
gtest.Assert(s.Contains(3), true)
t.Assert(s.Contains(2), false)
t.Assert(s.Contains(3), true)
s.AddIfNotExistFuncLock(3, func() interface{} {
return 4
})
gtest.Assert(s.Contains(3), true)
gtest.Assert(s.Contains(4), false)
t.Assert(s.Contains(3), true)
t.Assert(s.Contains(4), false)
})
}
func TestSet_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Set *gset.Set
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"set": []byte(`["k1","k2","k3"]`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Set.Size(), 3)
gtest.Assert(t.Set.Contains("k1"), true)
gtest.Assert(t.Set.Contains("k2"), true)
gtest.Assert(t.Set.Contains("k3"), true)
gtest.Assert(t.Set.Contains("k4"), false)
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Set.Size(), 3)
t.Assert(v.Set.Contains("k1"), true)
t.Assert(v.Set.Contains("k2"), true)
t.Assert(v.Set.Contains("k3"), true)
t.Assert(v.Set.Contains("k4"), false)
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"set": g.Slice{"k1", "k2", "k3"},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Set.Size(), 3)
gtest.Assert(t.Set.Contains("k1"), true)
gtest.Assert(t.Set.Contains("k2"), true)
gtest.Assert(t.Set.Contains("k3"), true)
gtest.Assert(t.Set.Contains("k4"), false)
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Set.Size(), 3)
t.Assert(v.Set.Contains("k1"), true)
t.Assert(v.Set.Contains("k2"), true)
t.Assert(v.Set.Contains("k3"), true)
t.Assert(v.Set.Contains("k4"), false)
})
}

View File

@ -21,30 +21,30 @@ import (
)
func TestIntSet_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.NewIntSet()
s.Add(1).Add(1).Add(2)
s.Add([]int{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)
t.Assert(s.Size(), 4)
t.AssertIN(1, s.Slice())
t.AssertIN(2, s.Slice())
t.AssertIN(3, s.Slice())
t.AssertIN(4, s.Slice())
t.AssertNI(0, s.Slice())
t.Assert(s.Contains(4), true)
t.Assert(s.Contains(5), false)
s.Remove(1)
gtest.Assert(s.Size(), 3)
t.Assert(s.Size(), 3)
s.Clear()
gtest.Assert(s.Size(), 0)
t.Assert(s.Size(), 0)
})
}
func TestIntSet_Iterator(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.NewIntSet()
s.Add(1).Add(2).Add(3)
gtest.Assert(s.Size(), 3)
t.Assert(s.Size(), 3)
a1 := garray.New(true)
a2 := garray.New(true)
@ -56,22 +56,22 @@ func TestIntSet_Iterator(t *testing.T) {
a2.Append(1)
return true
})
gtest.Assert(a1.Len(), 1)
gtest.Assert(a2.Len(), 3)
t.Assert(a1.Len(), 1)
t.Assert(a2.Len(), 3)
})
}
func TestIntSet_LockFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.NewIntSet()
s.Add(1).Add(2).Add(3)
gtest.Assert(s.Size(), 3)
t.Assert(s.Size(), 3)
s.LockFunc(func(m map[int]struct{}) {
delete(m, 1)
})
gtest.Assert(s.Size(), 2)
t.Assert(s.Size(), 2)
s.RLockFunc(func(m map[int]struct{}) {
gtest.Assert(m, map[int]struct{}{
t.Assert(m, map[int]struct{}{
3: struct{}{},
2: struct{}{},
})
@ -80,286 +80,286 @@ func TestIntSet_LockFunc(t *testing.T) {
}
func TestIntSet_Equal(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewIntSet()
s2 := gset.NewIntSet()
s3 := gset.NewIntSet()
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)
t.Assert(s1.Equal(s2), true)
t.Assert(s1.Equal(s3), false)
})
}
func TestIntSet_IsSubsetOf(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewIntSet()
s2 := gset.NewIntSet()
s3 := gset.NewIntSet()
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)
t.Assert(s1.IsSubsetOf(s2), true)
t.Assert(s2.IsSubsetOf(s3), true)
t.Assert(s1.IsSubsetOf(s3), true)
t.Assert(s2.IsSubsetOf(s1), false)
t.Assert(s3.IsSubsetOf(s2), false)
})
}
func TestIntSet_Union(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewIntSet()
s2 := gset.NewIntSet()
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)
t.Assert(s3.Contains(1), true)
t.Assert(s3.Contains(2), true)
t.Assert(s3.Contains(3), true)
t.Assert(s3.Contains(4), true)
})
}
func TestIntSet_Diff(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewIntSet()
s2 := gset.NewIntSet()
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)
t.Assert(s3.Contains(1), true)
t.Assert(s3.Contains(2), true)
t.Assert(s3.Contains(3), false)
t.Assert(s3.Contains(4), false)
})
}
func TestIntSet_Intersect(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewIntSet()
s2 := gset.NewIntSet()
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)
t.Assert(s3.Contains(1), false)
t.Assert(s3.Contains(2), false)
t.Assert(s3.Contains(3), true)
t.Assert(s3.Contains(4), false)
})
}
func TestIntSet_Complement(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewIntSet()
s2 := gset.NewIntSet()
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)
t.Assert(s3.Contains(1), false)
t.Assert(s3.Contains(2), false)
t.Assert(s3.Contains(4), true)
t.Assert(s3.Contains(5), true)
})
}
func TestIntSet_Size(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewIntSet(true)
s1.Add(1).Add(2).Add(3)
gtest.Assert(s1.Size(), 3)
t.Assert(s1.Size(), 3)
})
}
func TestIntSet_Merge(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewIntSet()
s2 := gset.NewIntSet()
s1.Add(1).Add(2).Add(3)
s2.Add(3).Add(4).Add(5)
s3 := s1.Merge(s2)
gtest.Assert(s3.Contains(1), true)
gtest.Assert(s3.Contains(5), true)
gtest.Assert(s3.Contains(6), false)
t.Assert(s3.Contains(1), true)
t.Assert(s3.Contains(5), true)
t.Assert(s3.Contains(6), false)
})
}
func TestIntSet_Join(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewIntSet()
s1.Add(1).Add(2).Add(3)
s3 := s1.Join(",")
gtest.Assert(strings.Contains(s3, "1"), true)
gtest.Assert(strings.Contains(s3, "2"), true)
gtest.Assert(strings.Contains(s3, "3"), true)
t.Assert(strings.Contains(s3, "1"), true)
t.Assert(strings.Contains(s3, "2"), true)
t.Assert(strings.Contains(s3, "3"), true)
})
}
func TestIntSet_String(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewIntSet()
s1.Add(1).Add(2).Add(3)
s3 := s1.String()
gtest.Assert(strings.Contains(s3, "["), true)
gtest.Assert(strings.Contains(s3, "]"), true)
gtest.Assert(strings.Contains(s3, "1"), true)
gtest.Assert(strings.Contains(s3, "2"), true)
gtest.Assert(strings.Contains(s3, "3"), true)
t.Assert(strings.Contains(s3, "["), true)
t.Assert(strings.Contains(s3, "]"), true)
t.Assert(strings.Contains(s3, "1"), true)
t.Assert(strings.Contains(s3, "2"), true)
t.Assert(strings.Contains(s3, "3"), true)
})
}
func TestIntSet_Sum(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewIntSet()
s1.Add(1).Add(2).Add(3)
s2 := gset.NewIntSet()
s2.Add(5).Add(6).Add(7)
gtest.Assert(s2.Sum(), 18)
t.Assert(s2.Sum(), 18)
})
}
func TestIntSet_Pop(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.NewIntSet()
s.Add(4).Add(2).Add(3)
gtest.Assert(s.Size(), 3)
gtest.AssertIN(s.Pop(), []int{4, 2, 3})
gtest.AssertIN(s.Pop(), []int{4, 2, 3})
gtest.Assert(s.Size(), 1)
t.Assert(s.Size(), 3)
t.AssertIN(s.Pop(), []int{4, 2, 3})
t.AssertIN(s.Pop(), []int{4, 2, 3})
t.Assert(s.Size(), 1)
})
}
func TestIntSet_Pops(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.NewIntSet()
s.Add(1).Add(4).Add(2).Add(3)
gtest.Assert(s.Size(), 4)
gtest.Assert(s.Pops(0), nil)
gtest.AssertIN(s.Pops(1), []int{1, 4, 2, 3})
gtest.Assert(s.Size(), 3)
t.Assert(s.Size(), 4)
t.Assert(s.Pops(0), nil)
t.AssertIN(s.Pops(1), []int{1, 4, 2, 3})
t.Assert(s.Size(), 3)
a := s.Pops(2)
gtest.Assert(len(a), 2)
gtest.AssertIN(a, []int{1, 4, 2, 3})
gtest.Assert(s.Size(), 1)
t.Assert(len(a), 2)
t.AssertIN(a, []int{1, 4, 2, 3})
t.Assert(s.Size(), 1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.NewIntSet(true)
a := []int{1, 2, 3, 4}
s.Add(a...)
gtest.Assert(s.Size(), 4)
gtest.Assert(s.Pops(-2), nil)
gtest.AssertIN(s.Pops(-1), a)
t.Assert(s.Size(), 4)
t.Assert(s.Pops(-2), nil)
t.AssertIN(s.Pops(-1), a)
})
}
func TestIntSet_Json(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []int{1, 3, 2, 4}
a1 := gset.NewIntSetFrom(s1)
b1, err1 := json.Marshal(a1)
b2, err2 := json.Marshal(s1)
gtest.Assert(len(b1), len(b2))
gtest.Assert(err1, err2)
t.Assert(len(b1), len(b2))
t.Assert(err1, err2)
a2 := gset.NewIntSet()
err2 = json.Unmarshal(b2, &a2)
gtest.Assert(err2, nil)
gtest.Assert(a2.Contains(1), true)
gtest.Assert(a2.Contains(2), true)
gtest.Assert(a2.Contains(3), true)
gtest.Assert(a2.Contains(4), true)
gtest.Assert(a2.Contains(5), false)
t.Assert(err2, nil)
t.Assert(a2.Contains(1), true)
t.Assert(a2.Contains(2), true)
t.Assert(a2.Contains(3), true)
t.Assert(a2.Contains(4), true)
t.Assert(a2.Contains(5), false)
var a3 gset.IntSet
err := json.Unmarshal(b2, &a3)
gtest.Assert(err, nil)
gtest.Assert(a2.Contains(1), true)
gtest.Assert(a2.Contains(2), true)
gtest.Assert(a2.Contains(3), true)
gtest.Assert(a2.Contains(4), true)
gtest.Assert(a2.Contains(5), false)
t.Assert(err, nil)
t.Assert(a2.Contains(1), true)
t.Assert(a2.Contains(2), true)
t.Assert(a2.Contains(3), true)
t.Assert(a2.Contains(4), true)
t.Assert(a2.Contains(5), false)
})
}
func TestIntSet_AddIfNotExistFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.NewIntSet(true)
s.Add(1)
gtest.Assert(s.Contains(1), true)
gtest.Assert(s.Contains(2), false)
t.Assert(s.Contains(1), true)
t.Assert(s.Contains(2), false)
s.AddIfNotExistFunc(2, func() int {
return 3
})
gtest.Assert(s.Contains(2), false)
gtest.Assert(s.Contains(3), true)
t.Assert(s.Contains(2), false)
t.Assert(s.Contains(3), true)
s.AddIfNotExistFunc(3, func() int {
return 4
})
gtest.Assert(s.Contains(3), true)
gtest.Assert(s.Contains(4), false)
t.Assert(s.Contains(3), true)
t.Assert(s.Contains(4), false)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.NewIntSet(true)
s.Add(1)
gtest.Assert(s.Contains(1), true)
gtest.Assert(s.Contains(2), false)
t.Assert(s.Contains(1), true)
t.Assert(s.Contains(2), false)
s.AddIfNotExistFuncLock(2, func() int {
return 3
})
gtest.Assert(s.Contains(2), false)
gtest.Assert(s.Contains(3), true)
t.Assert(s.Contains(2), false)
t.Assert(s.Contains(3), true)
s.AddIfNotExistFuncLock(3, func() int {
return 4
})
gtest.Assert(s.Contains(3), true)
gtest.Assert(s.Contains(4), false)
t.Assert(s.Contains(3), true)
t.Assert(s.Contains(4), false)
})
}
func TestIntSet_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Set *gset.IntSet
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"set": []byte(`[1,2,3]`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Set.Size(), 3)
gtest.Assert(t.Set.Contains(1), true)
gtest.Assert(t.Set.Contains(2), true)
gtest.Assert(t.Set.Contains(3), true)
gtest.Assert(t.Set.Contains(4), false)
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Set.Size(), 3)
t.Assert(v.Set.Contains(1), true)
t.Assert(v.Set.Contains(2), true)
t.Assert(v.Set.Contains(3), true)
t.Assert(v.Set.Contains(4), false)
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"set": g.Slice{1, 2, 3},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Set.Size(), 3)
gtest.Assert(t.Set.Contains(1), true)
gtest.Assert(t.Set.Contains(2), true)
gtest.Assert(t.Set.Contains(3), true)
gtest.Assert(t.Set.Contains(4), false)
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Set.Size(), 3)
t.Assert(v.Set.Contains(1), true)
t.Assert(v.Set.Contains(2), true)
t.Assert(v.Set.Contains(3), true)
t.Assert(v.Set.Contains(4), false)
})
}

View File

@ -21,30 +21,30 @@ import (
)
func TestStrSet_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.NewStrSet()
s.Add("1").Add("1").Add("2")
s.Add([]string{"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)
t.Assert(s.Size(), 4)
t.AssertIN("1", s.Slice())
t.AssertIN("2", s.Slice())
t.AssertIN("3", s.Slice())
t.AssertIN("4", s.Slice())
t.AssertNI("0", s.Slice())
t.Assert(s.Contains("4"), true)
t.Assert(s.Contains("5"), false)
s.Remove("1")
gtest.Assert(s.Size(), 3)
t.Assert(s.Size(), 3)
s.Clear()
gtest.Assert(s.Size(), 0)
t.Assert(s.Size(), 0)
})
}
func TestStrSet_Iterator(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.NewStrSet()
s.Add("1").Add("2").Add("3")
gtest.Assert(s.Size(), 3)
t.Assert(s.Size(), 3)
a1 := garray.New(true)
a2 := garray.New(true)
@ -56,22 +56,22 @@ func TestStrSet_Iterator(t *testing.T) {
a2.Append("1")
return true
})
gtest.Assert(a1.Len(), 1)
gtest.Assert(a2.Len(), 3)
t.Assert(a1.Len(), 1)
t.Assert(a2.Len(), 3)
})
}
func TestStrSet_LockFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.NewStrSet()
s.Add("1").Add("2").Add("3")
gtest.Assert(s.Size(), 3)
t.Assert(s.Size(), 3)
s.LockFunc(func(m map[string]struct{}) {
delete(m, "1")
})
gtest.Assert(s.Size(), 2)
t.Assert(s.Size(), 2)
s.RLockFunc(func(m map[string]struct{}) {
gtest.Assert(m, map[string]struct{}{
t.Assert(m, map[string]struct{}{
"3": struct{}{},
"2": struct{}{},
})
@ -80,322 +80,322 @@ func TestStrSet_LockFunc(t *testing.T) {
}
func TestStrSet_Equal(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewStrSet()
s2 := gset.NewStrSet()
s3 := gset.NewStrSet()
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)
t.Assert(s1.Equal(s2), true)
t.Assert(s1.Equal(s3), false)
})
}
func TestStrSet_IsSubsetOf(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewStrSet()
s2 := gset.NewStrSet()
s3 := gset.NewStrSet()
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)
t.Assert(s1.IsSubsetOf(s2), true)
t.Assert(s2.IsSubsetOf(s3), true)
t.Assert(s1.IsSubsetOf(s3), true)
t.Assert(s2.IsSubsetOf(s1), false)
t.Assert(s3.IsSubsetOf(s2), false)
})
}
func TestStrSet_Union(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewStrSet()
s2 := gset.NewStrSet()
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)
t.Assert(s3.Contains("1"), true)
t.Assert(s3.Contains("2"), true)
t.Assert(s3.Contains("3"), true)
t.Assert(s3.Contains("4"), true)
})
}
func TestStrSet_Diff(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewStrSet()
s2 := gset.NewStrSet()
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)
t.Assert(s3.Contains("1"), true)
t.Assert(s3.Contains("2"), true)
t.Assert(s3.Contains("3"), false)
t.Assert(s3.Contains("4"), false)
})
}
func TestStrSet_Intersect(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewStrSet()
s2 := gset.NewStrSet()
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)
t.Assert(s3.Contains("1"), false)
t.Assert(s3.Contains("2"), false)
t.Assert(s3.Contains("3"), true)
t.Assert(s3.Contains("4"), false)
})
}
func TestStrSet_Complement(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewStrSet()
s2 := gset.NewStrSet()
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)
t.Assert(s3.Contains("1"), false)
t.Assert(s3.Contains("2"), false)
t.Assert(s3.Contains("4"), true)
t.Assert(s3.Contains("5"), true)
})
}
func TestNewIntSetFrom(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewIntSetFrom([]int{1, 2, 3, 4})
s2 := gset.NewIntSetFrom([]int{5, 6, 7, 8})
gtest.Assert(s1.Contains(3), true)
gtest.Assert(s1.Contains(5), false)
gtest.Assert(s2.Contains(3), false)
gtest.Assert(s2.Contains(5), true)
t.Assert(s1.Contains(3), true)
t.Assert(s1.Contains(5), false)
t.Assert(s2.Contains(3), false)
t.Assert(s2.Contains(5), true)
})
}
func TestStrSet_Merge(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewStrSet()
s2 := gset.NewStrSet()
s1.Add("1").Add("2").Add("3")
s2.Add("3").Add("4").Add("5")
s3 := s1.Merge(s2)
gtest.Assert(s3.Contains("1"), true)
gtest.Assert(s3.Contains("6"), false)
gtest.Assert(s3.Contains("4"), true)
gtest.Assert(s3.Contains("5"), true)
t.Assert(s3.Contains("1"), true)
t.Assert(s3.Contains("6"), false)
t.Assert(s3.Contains("4"), true)
t.Assert(s3.Contains("5"), true)
})
}
func TestNewStrSetFrom(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewStrSetFrom([]string{"a", "b", "c"}, true)
gtest.Assert(s1.Contains("b"), true)
gtest.Assert(s1.Contains("d"), false)
t.Assert(s1.Contains("b"), true)
t.Assert(s1.Contains("d"), false)
})
}
func TestStrSet_Join(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewStrSetFrom([]string{"a", "b", "c"}, true)
str1 := s1.Join(",")
gtest.Assert(strings.Contains(str1, "b"), true)
gtest.Assert(strings.Contains(str1, "d"), false)
t.Assert(strings.Contains(str1, "b"), true)
t.Assert(strings.Contains(str1, "d"), false)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewStrSet()
s1.Add("a").Add(`"b"`).Add(`\c`)
str1 := s1.Join(",")
gtest.Assert(strings.Contains(str1, `"b"`), true)
gtest.Assert(strings.Contains(str1, `\c`), true)
gtest.Assert(strings.Contains(str1, `a`), true)
t.Assert(strings.Contains(str1, `"b"`), true)
t.Assert(strings.Contains(str1, `\c`), true)
t.Assert(strings.Contains(str1, `a`), true)
})
}
func TestStrSet_String(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewStrSetFrom([]string{"a", "b", "c"}, true)
str1 := s1.String()
gtest.Assert(strings.Contains(str1, "b"), true)
gtest.Assert(strings.Contains(str1, "d"), false)
t.Assert(strings.Contains(str1, "b"), true)
t.Assert(strings.Contains(str1, "d"), false)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.New(true)
s1.Add("a").Add("a2").Add("b").Add("c")
str1 := s1.String()
gtest.Assert(strings.Contains(str1, "["), true)
gtest.Assert(strings.Contains(str1, "]"), true)
gtest.Assert(strings.Contains(str1, "a2"), true)
t.Assert(strings.Contains(str1, "["), true)
t.Assert(strings.Contains(str1, "]"), true)
t.Assert(strings.Contains(str1, "a2"), true)
})
}
func TestStrSet_Sum(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewStrSetFrom([]string{"a", "b", "c"}, true)
s2 := gset.NewIntSetFrom([]int{2, 3, 4}, true)
gtest.Assert(s1.Sum(), 0)
gtest.Assert(s2.Sum(), 9)
t.Assert(s1.Sum(), 0)
t.Assert(s2.Sum(), 9)
})
}
func TestStrSet_Size(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewStrSetFrom([]string{"a", "b", "c"}, true)
gtest.Assert(s1.Size(), 3)
t.Assert(s1.Size(), 3)
})
}
func TestStrSet_Remove(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := gset.NewStrSetFrom([]string{"a", "b", "c"}, true)
s1 = s1.Remove("b")
gtest.Assert(s1.Contains("b"), false)
gtest.Assert(s1.Contains("c"), true)
t.Assert(s1.Contains("b"), false)
t.Assert(s1.Contains("c"), true)
})
}
func TestStrSet_Pop(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a := []string{"a", "b", "c", "d"}
s := gset.NewStrSetFrom(a, true)
gtest.Assert(s.Size(), 4)
gtest.AssertIN(s.Pop(), a)
gtest.Assert(s.Size(), 3)
gtest.AssertIN(s.Pop(), a)
gtest.Assert(s.Size(), 2)
t.Assert(s.Size(), 4)
t.AssertIN(s.Pop(), a)
t.Assert(s.Size(), 3)
t.AssertIN(s.Pop(), a)
t.Assert(s.Size(), 2)
})
}
func TestStrSet_Pops(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
a := []string{"a", "b", "c", "d"}
s := gset.NewStrSetFrom(a, true)
array := s.Pops(2)
gtest.Assert(len(array), 2)
gtest.Assert(s.Size(), 2)
gtest.AssertIN(array, a)
gtest.Assert(s.Pops(0), nil)
gtest.AssertIN(s.Pops(2), a)
gtest.Assert(s.Size(), 0)
t.Assert(len(array), 2)
t.Assert(s.Size(), 2)
t.AssertIN(array, a)
t.Assert(s.Pops(0), nil)
t.AssertIN(s.Pops(2), a)
t.Assert(s.Size(), 0)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.NewStrSet(true)
a := []string{"1", "2", "3", "4"}
s.Add(a...)
gtest.Assert(s.Size(), 4)
gtest.Assert(s.Pops(-2), nil)
gtest.AssertIN(s.Pops(-1), a)
t.Assert(s.Size(), 4)
t.Assert(s.Pops(-2), nil)
t.AssertIN(s.Pops(-1), a)
})
}
func TestStrSet_Json(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s1 := []string{"a", "b", "d", "c"}
a1 := gset.NewStrSetFrom(s1)
b1, err1 := json.Marshal(a1)
b2, err2 := json.Marshal(s1)
gtest.Assert(len(b1), len(b2))
gtest.Assert(err1, err2)
t.Assert(len(b1), len(b2))
t.Assert(err1, err2)
a2 := gset.NewStrSet()
err2 = json.Unmarshal(b2, &a2)
gtest.Assert(err2, nil)
gtest.Assert(a2.Contains("a"), true)
gtest.Assert(a2.Contains("b"), true)
gtest.Assert(a2.Contains("c"), true)
gtest.Assert(a2.Contains("d"), true)
gtest.Assert(a2.Contains("e"), false)
t.Assert(err2, nil)
t.Assert(a2.Contains("a"), true)
t.Assert(a2.Contains("b"), true)
t.Assert(a2.Contains("c"), true)
t.Assert(a2.Contains("d"), true)
t.Assert(a2.Contains("e"), false)
var a3 gset.StrSet
err := json.Unmarshal(b2, &a3)
gtest.Assert(err, nil)
gtest.Assert(a3.Contains("a"), true)
gtest.Assert(a3.Contains("b"), true)
gtest.Assert(a3.Contains("c"), true)
gtest.Assert(a3.Contains("d"), true)
gtest.Assert(a3.Contains("e"), false)
t.Assert(err, nil)
t.Assert(a3.Contains("a"), true)
t.Assert(a3.Contains("b"), true)
t.Assert(a3.Contains("c"), true)
t.Assert(a3.Contains("d"), true)
t.Assert(a3.Contains("e"), false)
})
}
func TestStrSet_AddIfNotExistFunc(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.NewStrSet(true)
s.Add("1")
gtest.Assert(s.Contains("1"), true)
gtest.Assert(s.Contains("2"), false)
t.Assert(s.Contains("1"), true)
t.Assert(s.Contains("2"), false)
s.AddIfNotExistFunc("2", func() string {
return "3"
})
gtest.Assert(s.Contains("2"), false)
gtest.Assert(s.Contains("3"), true)
t.Assert(s.Contains("2"), false)
t.Assert(s.Contains("3"), true)
s.AddIfNotExistFunc("3", func() string {
return "4"
})
gtest.Assert(s.Contains("3"), true)
gtest.Assert(s.Contains("4"), false)
t.Assert(s.Contains("3"), true)
t.Assert(s.Contains("4"), false)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := gset.NewStrSet(true)
s.Add("1")
gtest.Assert(s.Contains("1"), true)
gtest.Assert(s.Contains("2"), false)
t.Assert(s.Contains("1"), true)
t.Assert(s.Contains("2"), false)
s.AddIfNotExistFuncLock("2", func() string {
return "3"
})
gtest.Assert(s.Contains("2"), false)
gtest.Assert(s.Contains("3"), true)
t.Assert(s.Contains("2"), false)
t.Assert(s.Contains("3"), true)
s.AddIfNotExistFuncLock("3", func() string {
return "4"
})
gtest.Assert(s.Contains("3"), true)
gtest.Assert(s.Contains("4"), false)
t.Assert(s.Contains("3"), true)
t.Assert(s.Contains("4"), false)
})
}
func TestStrSet_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Set *gset.StrSet
}
// JSON
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"set": []byte(`["1","2","3"]`),
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Set.Size(), 3)
gtest.Assert(t.Set.Contains("1"), true)
gtest.Assert(t.Set.Contains("2"), true)
gtest.Assert(t.Set.Contains("3"), true)
gtest.Assert(t.Set.Contains("4"), false)
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Set.Size(), 3)
t.Assert(v.Set.Contains("1"), true)
t.Assert(v.Set.Contains("2"), true)
t.Assert(v.Set.Contains("3"), true)
t.Assert(v.Set.Contains("4"), false)
})
// Map
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"set": g.SliceStr{"1", "2", "3"},
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Set.Size(), 3)
gtest.Assert(t.Set.Contains("1"), true)
gtest.Assert(t.Set.Contains("2"), true)
gtest.Assert(t.Set.Contains("3"), true)
gtest.Assert(t.Set.Contains("4"), false)
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Set.Size(), 3)
t.Assert(v.Set.Contains("1"), true)
t.Assert(v.Set.Contains("2"), true)
t.Assert(v.Set.Contains("3"), true)
t.Assert(v.Set.Contains("4"), false)
})
}

View File

@ -17,96 +17,99 @@ import (
)
func Test_AVLTree_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewAVLTree(gutil.ComparatorString)
m.Set("key1", "val1")
gtest.Assert(m.Keys(), []interface{}{"key1"})
t.Assert(m.Keys(), []interface{}{"key1"})
gtest.Assert(m.Get("key1"), "val1")
gtest.Assert(m.Size(), 1)
gtest.Assert(m.IsEmpty(), false)
t.Assert(m.Get("key1"), "val1")
t.Assert(m.Size(), 1)
t.Assert(m.IsEmpty(), false)
gtest.Assert(m.GetOrSet("key2", "val2"), "val2")
gtest.Assert(m.GetOrSet("key2", "val2"), "val2")
gtest.Assert(m.SetIfNotExist("key2", "val2"), false)
t.Assert(m.GetOrSet("key2", "val2"), "val2")
t.Assert(m.GetOrSet("key2", "val2"), "val2")
t.Assert(m.SetIfNotExist("key2", "val2"), false)
gtest.Assert(m.SetIfNotExist("key3", "val3"), true)
t.Assert(m.SetIfNotExist("key3", "val3"), true)
gtest.Assert(m.Remove("key2"), "val2")
gtest.Assert(m.Contains("key2"), false)
t.Assert(m.Remove("key2"), "val2")
t.Assert(m.Contains("key2"), false)
gtest.AssertIN("key3", m.Keys())
gtest.AssertIN("key1", m.Keys())
gtest.AssertIN("val3", m.Values())
gtest.AssertIN("val1", m.Values())
t.AssertIN("key3", m.Keys())
t.AssertIN("key1", m.Keys())
t.AssertIN("val3", m.Values())
t.AssertIN("val1", m.Values())
m.Sets(map[interface{}]interface{}{"key3": "val3", "key1": "val1"})
m.Flip()
gtest.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val1": "key1"})
t.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val1": "key1"})
m.Flip(gutil.ComparatorString)
gtest.Assert(m.Map(), map[interface{}]interface{}{"key3": "val3", "key1": "val1"})
t.Assert(m.Map(), map[interface{}]interface{}{"key3": "val3", "key1": "val1"})
m.Clear()
gtest.Assert(m.Size(), 0)
gtest.Assert(m.IsEmpty(), true)
t.Assert(m.Size(), 0)
t.Assert(m.IsEmpty(), true)
m2 := gtree.NewAVLTreeFrom(gutil.ComparatorString, map[interface{}]interface{}{1: 1, "key1": "val1"})
gtest.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"})
t.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"})
})
}
func Test_AVLTree_Set_Fun(t *testing.T) {
//GetOrSetFunc lock or unlock
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewAVLTree(gutil.ComparatorString)
gtest.Assert(m.GetOrSetFunc("fun", getValue), 3)
gtest.Assert(m.GetOrSetFunc("fun", getValue), 3)
gtest.Assert(m.GetOrSetFuncLock("funlock", getValue), 3)
gtest.Assert(m.GetOrSetFuncLock("funlock", getValue), 3)
gtest.Assert(m.Get("funlock"), 3)
gtest.Assert(m.Get("fun"), 3)
t.Assert(m.GetOrSetFunc("fun", getValue), 3)
t.Assert(m.GetOrSetFunc("fun", getValue), 3)
t.Assert(m.GetOrSetFuncLock("funlock", getValue), 3)
t.Assert(m.GetOrSetFuncLock("funlock", getValue), 3)
t.Assert(m.Get("funlock"), 3)
t.Assert(m.Get("fun"), 3)
})
//SetIfNotExistFunc lock or unlock
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewAVLTree(gutil.ComparatorString)
gtest.Assert(m.SetIfNotExistFunc("fun", getValue), true)
gtest.Assert(m.SetIfNotExistFunc("fun", getValue), false)
gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), true)
gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false)
gtest.Assert(m.Get("funlock"), 3)
gtest.Assert(m.Get("fun"), 3)
t.Assert(m.SetIfNotExistFunc("fun", getValue), true)
t.Assert(m.SetIfNotExistFunc("fun", getValue), false)
t.Assert(m.SetIfNotExistFuncLock("funlock", getValue), true)
t.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false)
t.Assert(m.Get("funlock"), 3)
t.Assert(m.Get("fun"), 3)
})
}
func Test_AVLTree_Get_Set_Var(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewAVLTree(gutil.ComparatorString)
gtest.AssertEQ(m.SetIfNotExist("key1", "val1"), true)
gtest.AssertEQ(m.SetIfNotExist("key1", "val1"), false)
gtest.AssertEQ(m.GetVarOrSet("key1", "val1"), gvar.New("val1", true))
gtest.AssertEQ(m.GetVar("key1"), gvar.New("val1", true))
t.AssertEQ(m.SetIfNotExist("key1", "val1"), true)
t.AssertEQ(m.SetIfNotExist("key1", "val1"), false)
t.AssertEQ(m.GetVarOrSet("key1", "val1"), gvar.New("val1", true))
t.AssertEQ(m.GetVar("key1"), gvar.New("val1", true))
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewAVLTree(gutil.ComparatorString)
gtest.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true))
gtest.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true))
gtest.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true))
gtest.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true))
t.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true))
t.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true))
t.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true))
t.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true))
})
}
func Test_AVLTree_Batch(t *testing.T) {
m := gtree.NewAVLTree(gutil.ComparatorString)
m.Sets(map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
gtest.Assert(m.Map(), map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
m.Removes([]interface{}{"key1", 1})
gtest.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"})
gtest.C(t, func(t *gtest.T) {
m := gtree.NewAVLTree(gutil.ComparatorString)
m.Sets(map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
t.Assert(m.Map(), map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
m.Removes([]interface{}{"key1", 1})
t.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"})
})
}
func Test_AVLTree_Iterator(t *testing.T) {
keys := []string{"1", "key1", "key2", "key3", "key4"}
keyLen := len(keys)
index := 0
@ -114,23 +117,26 @@ func Test_AVLTree_Iterator(t *testing.T) {
expect := map[interface{}]interface{}{"key4": "val4", 1: 1, "key1": "val1", "key2": "val2", "key3": "val3"}
m := gtree.NewAVLTreeFrom(gutil.ComparatorString, expect)
m.Iterator(func(k interface{}, v interface{}) bool {
gtest.Assert(k, keys[index])
index++
gtest.Assert(expect[k], v)
return true
})
m.IteratorDesc(func(k interface{}, v interface{}) bool {
index--
gtest.Assert(k, keys[index])
gtest.Assert(expect[k], v)
return true
gtest.C(t, func(t *gtest.T) {
m.Iterator(func(k interface{}, v interface{}) bool {
t.Assert(k, keys[index])
index++
t.Assert(expect[k], v)
return true
})
m.IteratorDesc(func(k interface{}, v interface{}) bool {
index--
t.Assert(k, keys[index])
t.Assert(expect[k], v)
return true
})
})
m.Print()
// 断言返回值对遍历控制
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := 0
j := 0
m.Iterator(func(k interface{}, v interface{}) bool {
@ -141,11 +147,11 @@ func Test_AVLTree_Iterator(t *testing.T) {
j++
return false
})
gtest.Assert(i, keyLen)
gtest.Assert(j, 1)
t.Assert(i, keyLen)
t.Assert(j, 1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := 0
j := 0
m.IteratorDesc(func(k interface{}, v interface{}) bool {
@ -156,8 +162,8 @@ func Test_AVLTree_Iterator(t *testing.T) {
j++
return false
})
gtest.Assert(i, keyLen)
gtest.Assert(j, 1)
t.Assert(i, keyLen)
t.Assert(j, 1)
})
}
@ -169,27 +175,27 @@ func Test_AVLTree_IteratorFrom(t *testing.T) {
}
tree := gtree.NewAVLTreeFrom(gutil.ComparatorInt, m)
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
n := 5
tree.IteratorFrom(5, true, func(key, value interface{}) bool {
gtest.Assert(n, key)
gtest.Assert(n*10, value)
t.Assert(n, key)
t.Assert(n*10, value)
n++
return true
})
i := 5
tree.IteratorAscFrom(5, true, func(key, value interface{}) bool {
gtest.Assert(i, key)
gtest.Assert(i*10, value)
t.Assert(i, key)
t.Assert(i*10, value)
i++
return true
})
j := 5
tree.IteratorDescFrom(5, true, func(key, value interface{}) bool {
gtest.Assert(j, key)
gtest.Assert(j*10, value)
t.Assert(j, key)
t.Assert(j*10, value)
j--
return true
})
@ -197,31 +203,33 @@ func Test_AVLTree_IteratorFrom(t *testing.T) {
}
func Test_AVLTree_Clone(t *testing.T) {
//clone 方法是深克隆
m := gtree.NewAVLTreeFrom(gutil.ComparatorString, map[interface{}]interface{}{1: 1, "key1": "val1"})
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
gtest.AssertIN(1, m_clone.Keys())
gtest.C(t, func(t *gtest.T) {
//clone 方法是深克隆
m := gtree.NewAVLTreeFrom(gutil.ComparatorString, map[interface{}]interface{}{1: 1, "key1": "val1"})
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
t.AssertIN(1, m_clone.Keys())
m_clone.Remove("key1")
//修改clone map,原 map 不影响
gtest.AssertIN("key1", m.Keys())
m_clone.Remove("key1")
//修改clone map,原 map 不影响
t.AssertIN("key1", m.Keys())
})
}
func Test_AVLTree_LRNode(t *testing.T) {
expect := map[interface{}]interface{}{"key4": "val4", "key1": "val1", "key2": "val2", "key3": "val3"}
//safe
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewAVLTreeFrom(gutil.ComparatorString, expect)
gtest.Assert(m.Left().Key, "key1")
gtest.Assert(m.Right().Key, "key4")
t.Assert(m.Left().Key, "key1")
t.Assert(m.Right().Key, "key4")
})
//unsafe
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewAVLTreeFrom(gutil.ComparatorString, expect, true)
gtest.Assert(m.Left().Key, "key1")
gtest.Assert(m.Right().Key, "key4")
t.Assert(m.Left().Key, "key1")
t.Assert(m.Right().Key, "key4")
})
}
@ -237,34 +245,34 @@ func Test_AVLTree_CeilingFloor(t *testing.T) {
8: "val8",
4: "val4"}
//found and eq
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewAVLTreeFrom(gutil.ComparatorInt, expect)
c, cf := m.Ceiling(8)
gtest.Assert(cf, true)
gtest.Assert(c.Value, "val8")
t.Assert(cf, true)
t.Assert(c.Value, "val8")
f, ff := m.Floor(20)
gtest.Assert(ff, true)
gtest.Assert(f.Value, "val20")
t.Assert(ff, true)
t.Assert(f.Value, "val20")
})
//found and neq
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewAVLTreeFrom(gutil.ComparatorInt, expect)
c, cf := m.Ceiling(9)
gtest.Assert(cf, true)
gtest.Assert(c.Value, "val10")
t.Assert(cf, true)
t.Assert(c.Value, "val10")
f, ff := m.Floor(5)
gtest.Assert(ff, true)
gtest.Assert(f.Value, "val4")
t.Assert(ff, true)
t.Assert(f.Value, "val4")
})
//nofound
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewAVLTreeFrom(gutil.ComparatorInt, expect)
c, cf := m.Ceiling(21)
gtest.Assert(cf, false)
gtest.Assert(c, nil)
t.Assert(cf, false)
t.Assert(c, nil)
f, ff := m.Floor(-1)
gtest.Assert(ff, false)
gtest.Assert(f, nil)
t.Assert(ff, false)
t.Assert(f, nil)
})
}
@ -274,11 +282,11 @@ func Test_AVLTree_Remove(t *testing.T) {
m.Set(i, fmt.Sprintf("val%d", i))
}
expect := m.Map()
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
for k, v := range expect {
m1 := m.Clone()
gtest.Assert(m1.Remove(k), v)
gtest.Assert(m1.Remove(k), nil)
t.Assert(m1.Remove(k), v)
t.Assert(m1.Remove(k), nil)
}
})
}

View File

@ -17,88 +17,90 @@ import (
)
func Test_BTree_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewBTree(3, gutil.ComparatorString)
m.Set("key1", "val1")
gtest.Assert(m.Height(), 1)
t.Assert(m.Height(), 1)
gtest.Assert(m.Keys(), []interface{}{"key1"})
t.Assert(m.Keys(), []interface{}{"key1"})
gtest.Assert(m.Get("key1"), "val1")
gtest.Assert(m.Size(), 1)
gtest.Assert(m.IsEmpty(), false)
t.Assert(m.Get("key1"), "val1")
t.Assert(m.Size(), 1)
t.Assert(m.IsEmpty(), false)
gtest.Assert(m.GetOrSet("key2", "val2"), "val2")
gtest.Assert(m.SetIfNotExist("key2", "val2"), false)
t.Assert(m.GetOrSet("key2", "val2"), "val2")
t.Assert(m.SetIfNotExist("key2", "val2"), false)
gtest.Assert(m.SetIfNotExist("key3", "val3"), true)
t.Assert(m.SetIfNotExist("key3", "val3"), true)
gtest.Assert(m.Remove("key2"), "val2")
gtest.Assert(m.Contains("key2"), false)
t.Assert(m.Remove("key2"), "val2")
t.Assert(m.Contains("key2"), false)
gtest.AssertIN("key3", m.Keys())
gtest.AssertIN("key1", m.Keys())
gtest.AssertIN("val3", m.Values())
gtest.AssertIN("val1", m.Values())
t.AssertIN("key3", m.Keys())
t.AssertIN("key1", m.Keys())
t.AssertIN("val3", m.Values())
t.AssertIN("val1", m.Values())
m.Clear()
gtest.Assert(m.Size(), 0)
gtest.Assert(m.IsEmpty(), true)
t.Assert(m.Size(), 0)
t.Assert(m.IsEmpty(), true)
m2 := gtree.NewBTreeFrom(3, gutil.ComparatorString, map[interface{}]interface{}{1: 1, "key1": "val1"})
gtest.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"})
t.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"})
})
}
func Test_BTree_Set_Fun(t *testing.T) {
//GetOrSetFunc lock or unlock
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewBTree(3, gutil.ComparatorString)
gtest.Assert(m.GetOrSetFunc("fun", getValue), 3)
gtest.Assert(m.GetOrSetFunc("fun", getValue), 3)
gtest.Assert(m.GetOrSetFuncLock("funlock", getValue), 3)
gtest.Assert(m.GetOrSetFuncLock("funlock", getValue), 3)
gtest.Assert(m.Get("funlock"), 3)
gtest.Assert(m.Get("fun"), 3)
t.Assert(m.GetOrSetFunc("fun", getValue), 3)
t.Assert(m.GetOrSetFunc("fun", getValue), 3)
t.Assert(m.GetOrSetFuncLock("funlock", getValue), 3)
t.Assert(m.GetOrSetFuncLock("funlock", getValue), 3)
t.Assert(m.Get("funlock"), 3)
t.Assert(m.Get("fun"), 3)
})
//SetIfNotExistFunc lock or unlock
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewBTree(3, gutil.ComparatorString)
gtest.Assert(m.SetIfNotExistFunc("fun", getValue), true)
gtest.Assert(m.SetIfNotExistFunc("fun", getValue), false)
gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), true)
gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false)
gtest.Assert(m.Get("funlock"), 3)
gtest.Assert(m.Get("fun"), 3)
t.Assert(m.SetIfNotExistFunc("fun", getValue), true)
t.Assert(m.SetIfNotExistFunc("fun", getValue), false)
t.Assert(m.SetIfNotExistFuncLock("funlock", getValue), true)
t.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false)
t.Assert(m.Get("funlock"), 3)
t.Assert(m.Get("fun"), 3)
})
}
func Test_BTree_Get_Set_Var(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewBTree(3, gutil.ComparatorString)
gtest.AssertEQ(m.SetIfNotExist("key1", "val1"), true)
gtest.AssertEQ(m.SetIfNotExist("key1", "val1"), false)
gtest.AssertEQ(m.GetVarOrSet("key1", "val1"), gvar.New("val1", true))
gtest.AssertEQ(m.GetVar("key1"), gvar.New("val1", true))
t.AssertEQ(m.SetIfNotExist("key1", "val1"), true)
t.AssertEQ(m.SetIfNotExist("key1", "val1"), false)
t.AssertEQ(m.GetVarOrSet("key1", "val1"), gvar.New("val1", true))
t.AssertEQ(m.GetVar("key1"), gvar.New("val1", true))
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewBTree(3, gutil.ComparatorString)
gtest.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true))
gtest.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true))
gtest.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true))
gtest.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true))
t.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true))
t.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true))
t.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true))
t.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true))
})
}
func Test_BTree_Batch(t *testing.T) {
m := gtree.NewBTree(3, gutil.ComparatorString)
m.Sets(map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
gtest.Assert(m.Map(), map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
m.Removes([]interface{}{"key1", 1})
gtest.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"})
gtest.C(t, func(t *gtest.T) {
m := gtree.NewBTree(3, gutil.ComparatorString)
m.Sets(map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
t.Assert(m.Map(), map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
m.Removes([]interface{}{"key1", 1})
t.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"})
})
}
func Test_BTree_Iterator(t *testing.T) {
@ -109,23 +111,26 @@ func Test_BTree_Iterator(t *testing.T) {
expect := map[interface{}]interface{}{"key4": "val4", 1: 1, "key1": "val1", "key2": "val2", "key3": "val3"}
m := gtree.NewBTreeFrom(3, gutil.ComparatorString, expect)
m.Iterator(func(k interface{}, v interface{}) bool {
gtest.Assert(k, keys[index])
index++
gtest.Assert(expect[k], v)
return true
})
m.IteratorDesc(func(k interface{}, v interface{}) bool {
index--
gtest.Assert(k, keys[index])
gtest.Assert(expect[k], v)
return true
gtest.C(t, func(t *gtest.T) {
m.Iterator(func(k interface{}, v interface{}) bool {
t.Assert(k, keys[index])
index++
t.Assert(expect[k], v)
return true
})
m.IteratorDesc(func(k interface{}, v interface{}) bool {
index--
t.Assert(k, keys[index])
t.Assert(expect[k], v)
return true
})
})
m.Print()
// 断言返回值对遍历控制
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := 0
j := 0
m.Iterator(func(k interface{}, v interface{}) bool {
@ -136,11 +141,11 @@ func Test_BTree_Iterator(t *testing.T) {
j++
return false
})
gtest.Assert(i, keyLen)
gtest.Assert(j, 1)
t.Assert(i, keyLen)
t.Assert(j, 1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := 0
j := 0
m.IteratorDesc(func(k interface{}, v interface{}) bool {
@ -151,8 +156,8 @@ func Test_BTree_Iterator(t *testing.T) {
j++
return false
})
gtest.Assert(i, keyLen)
gtest.Assert(j, 1)
t.Assert(i, keyLen)
t.Assert(j, 1)
})
}
@ -163,27 +168,27 @@ func Test_BTree_IteratorFrom(t *testing.T) {
}
tree := gtree.NewBTreeFrom(3, gutil.ComparatorInt, m)
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
n := 5
tree.IteratorFrom(5, true, func(key, value interface{}) bool {
gtest.Assert(n, key)
gtest.Assert(n*10, value)
t.Assert(n, key)
t.Assert(n*10, value)
n++
return true
})
i := 5
tree.IteratorAscFrom(5, true, func(key, value interface{}) bool {
gtest.Assert(i, key)
gtest.Assert(i*10, value)
t.Assert(i, key)
t.Assert(i*10, value)
i++
return true
})
j := 5
tree.IteratorDescFrom(5, true, func(key, value interface{}) bool {
gtest.Assert(j, key)
gtest.Assert(j*10, value)
t.Assert(j, key)
t.Assert(j*10, value)
j--
return true
})
@ -191,31 +196,33 @@ func Test_BTree_IteratorFrom(t *testing.T) {
}
func Test_BTree_Clone(t *testing.T) {
//clone 方法是深克隆
m := gtree.NewBTreeFrom(3, gutil.ComparatorString, map[interface{}]interface{}{1: 1, "key1": "val1"})
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
gtest.AssertIN(1, m_clone.Keys())
gtest.C(t, func(t *gtest.T) {
//clone 方法是深克隆
m := gtree.NewBTreeFrom(3, gutil.ComparatorString, map[interface{}]interface{}{1: 1, "key1": "val1"})
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
t.AssertIN(1, m_clone.Keys())
m_clone.Remove("key1")
//修改clone map,原 map 不影响
gtest.AssertIN("key1", m.Keys())
m_clone.Remove("key1")
//修改clone map,原 map 不影响
t.AssertIN("key1", m.Keys())
})
}
func Test_BTree_LRNode(t *testing.T) {
expect := map[interface{}]interface{}{"key4": "val4", "key1": "val1", "key2": "val2", "key3": "val3"}
//safe
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewBTreeFrom(3, gutil.ComparatorString, expect)
gtest.Assert(m.Left().Key, "key1")
gtest.Assert(m.Right().Key, "key4")
t.Assert(m.Left().Key, "key1")
t.Assert(m.Right().Key, "key4")
})
//unsafe
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewBTreeFrom(3, gutil.ComparatorString, expect, true)
gtest.Assert(m.Left().Key, "key1")
gtest.Assert(m.Right().Key, "key4")
t.Assert(m.Left().Key, "key1")
t.Assert(m.Right().Key, "key4")
})
}
@ -225,11 +232,11 @@ func Test_BTree_Remove(t *testing.T) {
m.Set(i, fmt.Sprintf("val%d", i))
}
expect := m.Map()
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
for k, v := range expect {
m1 := m.Clone()
gtest.Assert(m1.Remove(k), v)
gtest.Assert(m1.Remove(k), nil)
t.Assert(m1.Remove(k), v)
t.Assert(m1.Remove(k), nil)
}
})
}

View File

@ -21,94 +21,96 @@ func getValue() interface{} {
}
func Test_RedBlackTree_Basic(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewRedBlackTree(gutil.ComparatorString)
m.Set("key1", "val1")
gtest.Assert(m.Keys(), []interface{}{"key1"})
t.Assert(m.Keys(), []interface{}{"key1"})
gtest.Assert(m.Get("key1"), "val1")
gtest.Assert(m.Size(), 1)
gtest.Assert(m.IsEmpty(), false)
t.Assert(m.Get("key1"), "val1")
t.Assert(m.Size(), 1)
t.Assert(m.IsEmpty(), false)
gtest.Assert(m.GetOrSet("key2", "val2"), "val2")
gtest.Assert(m.GetOrSet("key2", "val2"), "val2")
gtest.Assert(m.SetIfNotExist("key2", "val2"), false)
t.Assert(m.GetOrSet("key2", "val2"), "val2")
t.Assert(m.GetOrSet("key2", "val2"), "val2")
t.Assert(m.SetIfNotExist("key2", "val2"), false)
gtest.Assert(m.SetIfNotExist("key3", "val3"), true)
t.Assert(m.SetIfNotExist("key3", "val3"), true)
gtest.Assert(m.Remove("key2"), "val2")
gtest.Assert(m.Contains("key2"), false)
t.Assert(m.Remove("key2"), "val2")
t.Assert(m.Contains("key2"), false)
gtest.AssertIN("key3", m.Keys())
gtest.AssertIN("key1", m.Keys())
gtest.AssertIN("val3", m.Values())
gtest.AssertIN("val1", m.Values())
t.AssertIN("key3", m.Keys())
t.AssertIN("key1", m.Keys())
t.AssertIN("val3", m.Values())
t.AssertIN("val1", m.Values())
m.Sets(map[interface{}]interface{}{"key3": "val3", "key1": "val1"})
m.Flip()
gtest.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val1": "key1"})
t.Assert(m.Map(), map[interface{}]interface{}{"val3": "key3", "val1": "key1"})
m.Flip(gutil.ComparatorString)
gtest.Assert(m.Map(), map[interface{}]interface{}{"key3": "val3", "key1": "val1"})
t.Assert(m.Map(), map[interface{}]interface{}{"key3": "val3", "key1": "val1"})
m.Clear()
gtest.Assert(m.Size(), 0)
gtest.Assert(m.IsEmpty(), true)
t.Assert(m.Size(), 0)
t.Assert(m.IsEmpty(), true)
m2 := gtree.NewRedBlackTreeFrom(gutil.ComparatorString, map[interface{}]interface{}{1: 1, "key1": "val1"})
gtest.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"})
t.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"})
})
}
func Test_RedBlackTree_Set_Fun(t *testing.T) {
//GetOrSetFunc lock or unlock
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewRedBlackTree(gutil.ComparatorString)
gtest.Assert(m.GetOrSetFunc("fun", getValue), 3)
gtest.Assert(m.GetOrSetFunc("fun", getValue), 3)
gtest.Assert(m.GetOrSetFuncLock("funlock", getValue), 3)
gtest.Assert(m.GetOrSetFuncLock("funlock", getValue), 3)
gtest.Assert(m.Get("funlock"), 3)
gtest.Assert(m.Get("fun"), 3)
t.Assert(m.GetOrSetFunc("fun", getValue), 3)
t.Assert(m.GetOrSetFunc("fun", getValue), 3)
t.Assert(m.GetOrSetFuncLock("funlock", getValue), 3)
t.Assert(m.GetOrSetFuncLock("funlock", getValue), 3)
t.Assert(m.Get("funlock"), 3)
t.Assert(m.Get("fun"), 3)
})
//SetIfNotExistFunc lock or unlock
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewRedBlackTree(gutil.ComparatorString)
gtest.Assert(m.SetIfNotExistFunc("fun", getValue), true)
gtest.Assert(m.SetIfNotExistFunc("fun", getValue), false)
gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), true)
gtest.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false)
gtest.Assert(m.Get("funlock"), 3)
gtest.Assert(m.Get("fun"), 3)
t.Assert(m.SetIfNotExistFunc("fun", getValue), true)
t.Assert(m.SetIfNotExistFunc("fun", getValue), false)
t.Assert(m.SetIfNotExistFuncLock("funlock", getValue), true)
t.Assert(m.SetIfNotExistFuncLock("funlock", getValue), false)
t.Assert(m.Get("funlock"), 3)
t.Assert(m.Get("fun"), 3)
})
}
func Test_RedBlackTree_Get_Set_Var(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewRedBlackTree(gutil.ComparatorString)
gtest.AssertEQ(m.SetIfNotExist("key1", "val1"), true)
gtest.AssertEQ(m.SetIfNotExist("key1", "val1"), false)
gtest.AssertEQ(m.GetVarOrSet("key1", "val1"), gvar.New("val1", true))
gtest.AssertEQ(m.GetVar("key1"), gvar.New("val1", true))
t.AssertEQ(m.SetIfNotExist("key1", "val1"), true)
t.AssertEQ(m.SetIfNotExist("key1", "val1"), false)
t.AssertEQ(m.GetVarOrSet("key1", "val1"), gvar.New("val1", true))
t.AssertEQ(m.GetVar("key1"), gvar.New("val1", true))
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewRedBlackTree(gutil.ComparatorString)
gtest.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true))
gtest.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true))
gtest.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true))
gtest.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true))
t.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true))
t.AssertEQ(m.GetVarOrSetFunc("fun", getValue), gvar.New(3, true))
t.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true))
t.AssertEQ(m.GetVarOrSetFuncLock("funlock", getValue), gvar.New(3, true))
})
}
func Test_RedBlackTree_Batch(t *testing.T) {
m := gtree.NewRedBlackTree(gutil.ComparatorString)
m.Sets(map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
gtest.Assert(m.Map(), map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
m.Removes([]interface{}{"key1", 1})
gtest.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"})
gtest.C(t, func(t *gtest.T) {
m := gtree.NewRedBlackTree(gutil.ComparatorString)
m.Sets(map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
t.Assert(m.Map(), map[interface{}]interface{}{1: 1, "key1": "val1", "key2": "val2", "key3": "val3"})
m.Removes([]interface{}{"key1", 1})
t.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"})
})
}
func Test_RedBlackTree_Iterator(t *testing.T) {
@ -117,25 +119,27 @@ func Test_RedBlackTree_Iterator(t *testing.T) {
index := 0
expect := map[interface{}]interface{}{"key4": "val4", 1: 1, "key1": "val1", "key2": "val2", "key3": "val3"}
m := gtree.NewRedBlackTreeFrom(gutil.ComparatorString, expect)
m.Iterator(func(k interface{}, v interface{}) bool {
gtest.Assert(k, keys[index])
index++
gtest.Assert(expect[k], v)
return true
})
m.IteratorDesc(func(k interface{}, v interface{}) bool {
index--
gtest.Assert(k, keys[index])
gtest.Assert(expect[k], v)
return true
})
gtest.C(t, func(t *gtest.T) {
m.Iterator(func(k interface{}, v interface{}) bool {
t.Assert(k, keys[index])
index++
t.Assert(expect[k], v)
return true
})
m.IteratorDesc(func(k interface{}, v interface{}) bool {
index--
t.Assert(k, keys[index])
t.Assert(expect[k], v)
return true
})
})
m.Print()
// 断言返回值对遍历控制
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := 0
j := 0
m.Iterator(func(k interface{}, v interface{}) bool {
@ -146,11 +150,11 @@ func Test_RedBlackTree_Iterator(t *testing.T) {
j++
return false
})
gtest.Assert(i, keyLen)
gtest.Assert(j, 1)
t.Assert(i, keyLen)
t.Assert(j, 1)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := 0
j := 0
m.IteratorDesc(func(k interface{}, v interface{}) bool {
@ -161,8 +165,8 @@ func Test_RedBlackTree_Iterator(t *testing.T) {
j++
return false
})
gtest.Assert(i, keyLen)
gtest.Assert(j, 1)
t.Assert(i, keyLen)
t.Assert(j, 1)
})
}
@ -173,27 +177,27 @@ func Test_RedBlackTree_IteratorFrom(t *testing.T) {
}
tree := gtree.NewRedBlackTreeFrom(gutil.ComparatorInt, m)
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
n := 5
tree.IteratorFrom(5, true, func(key, value interface{}) bool {
gtest.Assert(n, key)
gtest.Assert(n*10, value)
t.Assert(n, key)
t.Assert(n*10, value)
n++
return true
})
i := 5
tree.IteratorAscFrom(5, true, func(key, value interface{}) bool {
gtest.Assert(i, key)
gtest.Assert(i*10, value)
t.Assert(i, key)
t.Assert(i*10, value)
i++
return true
})
j := 5
tree.IteratorDescFrom(5, true, func(key, value interface{}) bool {
gtest.Assert(j, key)
gtest.Assert(j*10, value)
t.Assert(j, key)
t.Assert(j*10, value)
j--
return true
})
@ -201,31 +205,33 @@ func Test_RedBlackTree_IteratorFrom(t *testing.T) {
}
func Test_RedBlackTree_Clone(t *testing.T) {
//clone 方法是深克隆
m := gtree.NewRedBlackTreeFrom(gutil.ComparatorString, map[interface{}]interface{}{1: 1, "key1": "val1"})
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
gtest.AssertIN(1, m_clone.Keys())
gtest.C(t, func(t *gtest.T) {
//clone 方法是深克隆
m := gtree.NewRedBlackTreeFrom(gutil.ComparatorString, map[interface{}]interface{}{1: 1, "key1": "val1"})
m_clone := m.Clone()
m.Remove(1)
//修改原 map,clone 后的 map 不影响
t.AssertIN(1, m_clone.Keys())
m_clone.Remove("key1")
//修改clone map,原 map 不影响
gtest.AssertIN("key1", m.Keys())
m_clone.Remove("key1")
//修改clone map,原 map 不影响
t.AssertIN("key1", m.Keys())
})
}
func Test_RedBlackTree_LRNode(t *testing.T) {
expect := map[interface{}]interface{}{"key4": "val4", "key1": "val1", "key2": "val2", "key3": "val3"}
//safe
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewRedBlackTreeFrom(gutil.ComparatorString, expect)
gtest.Assert(m.Left().Key, "key1")
gtest.Assert(m.Right().Key, "key4")
t.Assert(m.Left().Key, "key1")
t.Assert(m.Right().Key, "key4")
})
//unsafe
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewRedBlackTreeFrom(gutil.ComparatorString, expect, true)
gtest.Assert(m.Left().Key, "key1")
gtest.Assert(m.Right().Key, "key4")
t.Assert(m.Left().Key, "key1")
t.Assert(m.Right().Key, "key4")
})
}
@ -241,34 +247,34 @@ func Test_RedBlackTree_CeilingFloor(t *testing.T) {
8: "val8",
4: "val4"}
//found and eq
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewRedBlackTreeFrom(gutil.ComparatorInt, expect)
c, cf := m.Ceiling(8)
gtest.Assert(cf, true)
gtest.Assert(c.Value, "val8")
t.Assert(cf, true)
t.Assert(c.Value, "val8")
f, ff := m.Floor(20)
gtest.Assert(ff, true)
gtest.Assert(f.Value, "val20")
t.Assert(ff, true)
t.Assert(f.Value, "val20")
})
//found and neq
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewRedBlackTreeFrom(gutil.ComparatorInt, expect)
c, cf := m.Ceiling(9)
gtest.Assert(cf, true)
gtest.Assert(c.Value, "val10")
t.Assert(cf, true)
t.Assert(c.Value, "val10")
f, ff := m.Floor(5)
gtest.Assert(ff, true)
gtest.Assert(f.Value, "val4")
t.Assert(ff, true)
t.Assert(f.Value, "val4")
})
//nofound
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := gtree.NewRedBlackTreeFrom(gutil.ComparatorInt, expect)
c, cf := m.Ceiling(21)
gtest.Assert(cf, false)
gtest.Assert(c, nil)
t.Assert(cf, false)
t.Assert(c, nil)
f, ff := m.Floor(-1)
gtest.Assert(ff, false)
gtest.Assert(f, nil)
t.Assert(ff, false)
t.Assert(f, nil)
})
}
@ -278,11 +284,11 @@ func Test_RedBlackTree_Remove(t *testing.T) {
m.Set(i, fmt.Sprintf("val%d", i))
}
expect := m.Map()
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
for k, v := range expect {
m1 := m.Clone()
gtest.Assert(m1.Remove(k), v)
gtest.Assert(m1.Remove(k), nil)
t.Assert(m1.Remove(k), v)
t.Assert(m1.Remove(k), nil)
}
})
}

View File

@ -157,6 +157,12 @@ func BenchmarkBool_Val(b *testing.B) {
}
}
func BenchmarkBool_Cas(b *testing.B) {
for i := 0; i < b.N; i++ {
bl.Cas(false, true)
}
}
func BenchmarkString_Set(b *testing.B) {
for i := 0; i < b.N; i++ {
str.Set(strconv.Itoa(i))

View File

@ -16,110 +16,110 @@ import (
)
func Test_Bool(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := gtype.NewBool(true)
iClone := i.Clone()
gtest.AssertEQ(iClone.Set(false), true)
gtest.AssertEQ(iClone.Val(), false)
t.AssertEQ(iClone.Set(false), true)
t.AssertEQ(iClone.Val(), false)
i1 := gtype.NewBool(false)
iClone1 := i1.Clone()
gtest.AssertEQ(iClone1.Set(true), false)
gtest.AssertEQ(iClone1.Val(), true)
t.AssertEQ(iClone1.Set(true), false)
t.AssertEQ(iClone1.Val(), true)
//空参测试
i2 := gtype.NewBool()
gtest.AssertEQ(i2.Val(), false)
t.AssertEQ(i2.Val(), false)
})
}
func Test_Bool_JSON(t *testing.T) {
// Marshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := gtype.NewBool(true)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.Assert(b1, b2)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := gtype.NewBool(false)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.Assert(b1, b2)
})
// Unmarshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var err error
i := gtype.NewBool()
err = json.Unmarshal([]byte("true"), &i)
gtest.Assert(err, nil)
gtest.Assert(i.Val(), true)
t.Assert(err, nil)
t.Assert(i.Val(), true)
err = json.Unmarshal([]byte("false"), &i)
gtest.Assert(err, nil)
gtest.Assert(i.Val(), false)
t.Assert(err, nil)
t.Assert(i.Val(), false)
err = json.Unmarshal([]byte("1"), &i)
gtest.Assert(err, nil)
gtest.Assert(i.Val(), true)
t.Assert(err, nil)
t.Assert(i.Val(), true)
err = json.Unmarshal([]byte("0"), &i)
gtest.Assert(err, nil)
gtest.Assert(i.Val(), false)
t.Assert(err, nil)
t.Assert(i.Val(), false)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := gtype.NewBool(true)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.Assert(b1, b2)
i2 := gtype.NewBool()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), i.Val())
t.Assert(err, nil)
t.Assert(i2.Val(), i.Val())
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := gtype.NewBool(false)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.Assert(b1, b2)
i2 := gtype.NewBool()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), i.Val())
t.Assert(err, nil)
t.Assert(i2.Val(), i.Val())
})
}
func Test_Bool_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Var *gtype.Bool
}
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"var": "true",
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Var.Val(), true)
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Var.Val(), true)
})
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"var": "false",
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Var.Val(), false)
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Var.Val(), false)
})
}

View File

@ -17,13 +17,13 @@ import (
)
func Test_Byte(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var wg sync.WaitGroup
addTimes := 127
i := gtype.NewByte(byte(0))
iClone := i.Clone()
gtest.AssertEQ(iClone.Set(byte(1)), byte(0))
gtest.AssertEQ(iClone.Val(), byte(1))
t.AssertEQ(iClone.Set(byte(1)), byte(0))
t.AssertEQ(iClone.Val(), byte(1))
for index := 0; index < addTimes; index++ {
wg.Add(1)
go func() {
@ -32,46 +32,46 @@ func Test_Byte(t *testing.T) {
}()
}
wg.Wait()
gtest.AssertEQ(byte(addTimes), i.Val())
t.AssertEQ(byte(addTimes), i.Val())
//空参测试
i1 := gtype.NewByte()
gtest.AssertEQ(i1.Val(), byte(0))
t.AssertEQ(i1.Val(), byte(0))
})
}
func Test_Byte_JSON(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := gtype.NewByte(49)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.Assert(b1, b2)
})
// Unmarshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var err error
i := gtype.NewByte()
err = json.Unmarshal([]byte("49"), &i)
gtest.Assert(err, nil)
gtest.Assert(i.Val(), "49")
t.Assert(err, nil)
t.Assert(i.Val(), "49")
})
}
func Test_Byte_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Var *gtype.Byte
}
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"var": "2",
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Var.Val(), "2")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Var.Val(), "2")
})
}

View File

@ -16,48 +16,48 @@ import (
)
func Test_Bytes(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := gtype.NewBytes([]byte("abc"))
iClone := i.Clone()
gtest.AssertEQ(iClone.Set([]byte("123")), []byte("abc"))
gtest.AssertEQ(iClone.Val(), []byte("123"))
t.AssertEQ(iClone.Set([]byte("123")), []byte("abc"))
t.AssertEQ(iClone.Val(), []byte("123"))
//空参测试
i1 := gtype.NewBytes()
gtest.AssertEQ(i1.Val(), nil)
t.AssertEQ(i1.Val(), nil)
})
}
func Test_Bytes_JSON(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
b := []byte("i love gf")
i := gtype.NewBytes(b)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.Assert(b1, b2)
i2 := gtype.NewBytes()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), b)
t.Assert(err, nil)
t.Assert(i2.Val(), b)
})
}
func Test_Bytes_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Var *gtype.Bytes
}
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"var": "123",
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Var.Val(), "123")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Var.Val(), "123")
})
}

View File

@ -16,49 +16,49 @@ import (
)
func Test_Float32(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := gtype.NewFloat32(0)
iClone := i.Clone()
gtest.AssertEQ(iClone.Set(0.1), float32(0))
gtest.AssertEQ(iClone.Val(), float32(0.1))
t.AssertEQ(iClone.Set(0.1), float32(0))
t.AssertEQ(iClone.Val(), float32(0.1))
//空参测试
i1 := gtype.NewFloat32()
gtest.AssertEQ(i1.Val(), float32(0))
t.AssertEQ(i1.Val(), float32(0))
})
}
func Test_Float32_JSON(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
v := float32(math.MaxFloat32)
i := gtype.NewFloat32(v)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.Assert(b1, b2)
i2 := gtype.NewFloat32()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), v)
t.Assert(err, nil)
t.Assert(i2.Val(), v)
})
}
func Test_Float32_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Var *gtype.Float32
}
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"var": "123.456",
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Var.Val(), "123.456")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Var.Val(), "123.456")
})
}

View File

@ -16,47 +16,47 @@ import (
)
func Test_Float64(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := gtype.NewFloat64(0)
iClone := i.Clone()
gtest.AssertEQ(iClone.Set(0.1), float64(0))
gtest.AssertEQ(iClone.Val(), float64(0.1))
t.AssertEQ(iClone.Set(0.1), float64(0))
t.AssertEQ(iClone.Val(), float64(0.1))
//空参测试
i1 := gtype.NewFloat64()
gtest.AssertEQ(i1.Val(), float64(0))
t.AssertEQ(i1.Val(), float64(0))
})
}
func Test_Float64_JSON(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
v := math.MaxFloat64
i := gtype.NewFloat64(v)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.Assert(b1, b2)
i2 := gtype.NewFloat64()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), v)
t.Assert(err, nil)
t.Assert(i2.Val(), v)
})
}
func Test_Float64_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Var *gtype.Float64
}
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"var": "123.456",
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Var.Val(), "123.456")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Var.Val(), "123.456")
})
}

View File

@ -17,13 +17,13 @@ import (
)
func Test_Int32(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var wg sync.WaitGroup
addTimes := 1000
i := gtype.NewInt32(0)
iClone := i.Clone()
gtest.AssertEQ(iClone.Set(1), int32(0))
gtest.AssertEQ(iClone.Val(), int32(1))
t.AssertEQ(iClone.Set(1), int32(0))
t.AssertEQ(iClone.Val(), int32(1))
for index := 0; index < addTimes; index++ {
wg.Add(1)
go func() {
@ -32,44 +32,44 @@ func Test_Int32(t *testing.T) {
}()
}
wg.Wait()
gtest.AssertEQ(int32(addTimes), i.Val())
t.AssertEQ(int32(addTimes), i.Val())
//空参测试
i1 := gtype.NewInt32()
gtest.AssertEQ(i1.Val(), int32(0))
t.AssertEQ(i1.Val(), int32(0))
})
}
func Test_Int32_JSON(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
v := int32(math.MaxInt32)
i := gtype.NewInt32(v)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.Assert(b1, b2)
i2 := gtype.NewInt32()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), v)
t.Assert(err, nil)
t.Assert(i2.Val(), v)
})
}
func Test_Int32_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Var *gtype.Int32
}
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"var": "123",
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Var.Val(), "123")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Var.Val(), "123")
})
}

View File

@ -17,13 +17,13 @@ import (
)
func Test_Int64(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var wg sync.WaitGroup
addTimes := 1000
i := gtype.NewInt64(0)
iClone := i.Clone()
gtest.AssertEQ(iClone.Set(1), int64(0))
gtest.AssertEQ(iClone.Val(), int64(1))
t.AssertEQ(iClone.Set(1), int64(0))
t.AssertEQ(iClone.Val(), int64(1))
for index := 0; index < addTimes; index++ {
wg.Add(1)
go func() {
@ -32,43 +32,43 @@ func Test_Int64(t *testing.T) {
}()
}
wg.Wait()
gtest.AssertEQ(int64(addTimes), i.Val())
t.AssertEQ(int64(addTimes), i.Val())
//空参测试
i1 := gtype.NewInt64()
gtest.AssertEQ(i1.Val(), int64(0))
t.AssertEQ(i1.Val(), int64(0))
})
}
func Test_Int64_JSON(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := gtype.NewInt64(math.MaxInt64)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.Assert(b1, b2)
i2 := gtype.NewInt64()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), i)
t.Assert(err, nil)
t.Assert(i2.Val(), i)
})
}
func Test_Int64_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Var *gtype.Int64
}
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"var": "123",
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Var.Val(), "123")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Var.Val(), "123")
})
}

View File

@ -16,13 +16,13 @@ import (
)
func Test_Int(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var wg sync.WaitGroup
addTimes := 1000
i := gtype.NewInt(0)
iClone := i.Clone()
gtest.AssertEQ(iClone.Set(1), 0)
gtest.AssertEQ(iClone.Val(), 1)
t.AssertEQ(iClone.Set(1), 0)
t.AssertEQ(iClone.Val(), 1)
for index := 0; index < addTimes; index++ {
wg.Add(1)
go func() {
@ -31,44 +31,44 @@ func Test_Int(t *testing.T) {
}()
}
wg.Wait()
gtest.AssertEQ(addTimes, i.Val())
t.AssertEQ(addTimes, i.Val())
//空参测试
i1 := gtype.NewInt()
gtest.AssertEQ(i1.Val(), 0)
t.AssertEQ(i1.Val(), 0)
})
}
func Test_Int_JSON(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
v := 666
i := gtype.NewInt(v)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.Assert(b1, b2)
i2 := gtype.NewInt()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), v)
t.Assert(err, nil)
t.Assert(i2.Val(), v)
})
}
func Test_Int_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Var *gtype.Int
}
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"var": "123",
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Var.Val(), "123")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Var.Val(), "123")
})
}

View File

@ -15,50 +15,50 @@ import (
)
func Test_Interface(t *testing.T) {
gtest.Case(t, func() {
t := Temp{Name: "gf", Age: 18}
t1 := Temp{Name: "gf", Age: 19}
i := gtype.New(t)
gtest.C(t, func(t *gtest.T) {
t1 := Temp{Name: "gf", Age: 18}
t2 := Temp{Name: "gf", Age: 19}
i := gtype.New(t1)
iClone := i.Clone()
gtest.AssertEQ(iClone.Set(t1), t)
gtest.AssertEQ(iClone.Val().(Temp), t1)
t.AssertEQ(iClone.Set(t2), t1)
t.AssertEQ(iClone.Val().(Temp), t2)
//空参测试
i1 := gtype.New()
gtest.AssertEQ(i1.Val(), nil)
t.AssertEQ(i1.Val(), nil)
})
}
func Test_Interface_JSON(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := "i love gf"
i := gtype.New(s)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.Assert(b1, b2)
i2 := gtype.New()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), s)
t.Assert(err, nil)
t.Assert(i2.Val(), s)
})
}
func Test_Interface_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Var *gtype.Interface
}
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"var": "123",
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Var.Val(), "123")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Var.Val(), "123")
})
}

View File

@ -15,48 +15,48 @@ import (
)
func Test_String(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := gtype.NewString("abc")
iClone := i.Clone()
gtest.AssertEQ(iClone.Set("123"), "abc")
gtest.AssertEQ(iClone.Val(), "123")
t.AssertEQ(iClone.Set("123"), "abc")
t.AssertEQ(iClone.Val(), "123")
//空参测试
i1 := gtype.NewString()
gtest.AssertEQ(i1.Val(), "")
t.AssertEQ(i1.Val(), "")
})
}
func Test_String_JSON(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := "i love gf"
i1 := gtype.NewString(s)
b1, err1 := json.Marshal(i1)
b2, err2 := json.Marshal(i1.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.Assert(b1, b2)
i2 := gtype.NewString()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), s)
t.Assert(err, nil)
t.Assert(i2.Val(), s)
})
}
func Test_String_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Var *gtype.String
}
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"var": "123",
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Var.Val(), "123")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Var.Val(), "123")
})
}

View File

@ -17,13 +17,13 @@ import (
)
func Test_Uint32(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var wg sync.WaitGroup
addTimes := 1000
i := gtype.NewUint32(0)
iClone := i.Clone()
gtest.AssertEQ(iClone.Set(1), uint32(0))
gtest.AssertEQ(iClone.Val(), uint32(1))
t.AssertEQ(iClone.Set(1), uint32(0))
t.AssertEQ(iClone.Val(), uint32(1))
for index := 0; index < addTimes; index++ {
wg.Add(1)
go func() {
@ -32,43 +32,43 @@ func Test_Uint32(t *testing.T) {
}()
}
wg.Wait()
gtest.AssertEQ(uint32(addTimes), i.Val())
t.AssertEQ(uint32(addTimes), i.Val())
//空参测试
i1 := gtype.NewUint32()
gtest.AssertEQ(i1.Val(), uint32(0))
t.AssertEQ(i1.Val(), uint32(0))
})
}
func Test_Uint32_JSON(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := gtype.NewUint32(math.MaxUint32)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.Assert(b1, b2)
i2 := gtype.NewUint32()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), i)
t.Assert(err, nil)
t.Assert(i2.Val(), i)
})
}
func Test_Uint32_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Var *gtype.Uint32
}
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"var": "123",
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Var.Val(), "123")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Var.Val(), "123")
})
}

View File

@ -23,13 +23,13 @@ type Temp struct {
}
func Test_Uint64(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var wg sync.WaitGroup
addTimes := 1000
i := gtype.NewUint64(0)
iClone := i.Clone()
gtest.AssertEQ(iClone.Set(1), uint64(0))
gtest.AssertEQ(iClone.Val(), uint64(1))
t.AssertEQ(iClone.Set(1), uint64(0))
t.AssertEQ(iClone.Val(), uint64(1))
for index := 0; index < addTimes; index++ {
wg.Add(1)
go func() {
@ -38,42 +38,42 @@ func Test_Uint64(t *testing.T) {
}()
}
wg.Wait()
gtest.AssertEQ(uint64(addTimes), i.Val())
t.AssertEQ(uint64(addTimes), i.Val())
//空参测试
i1 := gtype.NewUint64()
gtest.AssertEQ(i1.Val(), uint64(0))
t.AssertEQ(i1.Val(), uint64(0))
})
}
func Test_Uint64_JSON(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := gtype.NewUint64(math.MaxUint64)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.Assert(b1, b2)
i2 := gtype.NewUint64()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), i)
t.Assert(err, nil)
t.Assert(i2.Val(), i)
})
}
func Test_Uint64_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Var *gtype.Uint64
}
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"var": "123",
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Var.Val(), "123")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Var.Val(), "123")
})
}

View File

@ -16,13 +16,13 @@ import (
)
func Test_Uint(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var wg sync.WaitGroup
addTimes := 1000
i := gtype.NewUint(0)
iClone := i.Clone()
gtest.AssertEQ(iClone.Set(1), uint(0))
gtest.AssertEQ(iClone.Val(), uint(1))
t.AssertEQ(iClone.Set(1), uint(0))
t.AssertEQ(iClone.Val(), uint(1))
for index := 0; index < addTimes; index++ {
wg.Add(1)
go func() {
@ -31,43 +31,43 @@ func Test_Uint(t *testing.T) {
}()
}
wg.Wait()
gtest.AssertEQ(uint(addTimes), i.Val())
t.AssertEQ(uint(addTimes), i.Val())
//空参测试
i1 := gtype.NewUint()
gtest.AssertEQ(i1.Val(), uint(0))
t.AssertEQ(i1.Val(), uint(0))
})
}
func Test_Uint_JSON(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
i := gtype.NewUint(666)
b1, err1 := json.Marshal(i)
b2, err2 := json.Marshal(i.Val())
gtest.Assert(err1, nil)
gtest.Assert(err2, nil)
gtest.Assert(b1, b2)
t.Assert(err1, nil)
t.Assert(err2, nil)
t.Assert(b1, b2)
i2 := gtype.NewUint()
err := json.Unmarshal(b2, &i2)
gtest.Assert(err, nil)
gtest.Assert(i2.Val(), i)
t.Assert(err, nil)
t.Assert(i2.Val(), i)
})
}
func Test_Uint_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Var *gtype.Uint
}
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"var": "123",
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Var.Val(), "123")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Var.Val(), "123")
})
}

View File

@ -46,6 +46,11 @@ func Create(value interface{}, safe ...bool) Var {
return v
}
// Clone does a shallow copy of current Var and returns a pointer to this Var.
func (v *Var) Clone() *Var {
return New(v.Val(), v.safe)
}
// Set sets <value> to <v>, and returns the old value.
func (v *Var) Set(value interface{}) (old interface{}) {
if v.safe {

View File

@ -22,66 +22,66 @@ import (
)
func Test_Set(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var v gvar.Var
v.Set(123.456)
gtest.Assert(v.Val(), 123.456)
t.Assert(v.Val(), 123.456)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var v gvar.Var
v.Set(123.456)
gtest.Assert(v.Val(), 123.456)
t.Assert(v.Val(), 123.456)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
v := gvar.Create(123.456)
gtest.Assert(v.Val(), 123.456)
t.Assert(v.Val(), 123.456)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
objOne := gvar.New("old", true)
objOneOld, _ := objOne.Set("new").(string)
gtest.Assert(objOneOld, "old")
t.Assert(objOneOld, "old")
objTwo := gvar.New("old", false)
objTwoOld, _ := objTwo.Set("new").(string)
gtest.Assert(objTwoOld, "old")
t.Assert(objTwoOld, "old")
})
}
func Test_Val(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
objOne := gvar.New(1, true)
objOneOld, _ := objOne.Val().(int)
gtest.Assert(objOneOld, 1)
t.Assert(objOneOld, 1)
objTwo := gvar.New(1, false)
objTwoOld, _ := objTwo.Val().(int)
gtest.Assert(objTwoOld, 1)
t.Assert(objTwoOld, 1)
})
}
func Test_Interface(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
objOne := gvar.New(1, true)
objOneOld, _ := objOne.Interface().(int)
gtest.Assert(objOneOld, 1)
t.Assert(objOneOld, 1)
objTwo := gvar.New(1, false)
objTwoOld, _ := objTwo.Interface().(int)
gtest.Assert(objTwoOld, 1)
t.Assert(objTwoOld, 1)
})
}
func Test_IsNil(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
objOne := gvar.New(nil, true)
gtest.Assert(objOne.IsNil(), true)
t.Assert(objOne.IsNil(), true)
objTwo := gvar.New("noNil", false)
gtest.Assert(objTwo.IsNil(), false)
t.Assert(objTwo.IsNil(), false)
})
}
func Test_Bytes(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
x := int32(1)
bytesBuffer := bytes.NewBuffer([]byte{})
binary.Write(bytesBuffer, binary.BigEndian, x)
@ -92,233 +92,233 @@ func Test_Bytes(t *testing.T) {
var y int32
binary.Read(bBuf, binary.BigEndian, &y)
gtest.Assert(x, y)
t.Assert(x, y)
})
}
func Test_String(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var str string = "hello"
objOne := gvar.New(str, true)
gtest.Assert(objOne.String(), str)
t.Assert(objOne.String(), str)
})
}
func Test_Bool(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var ok bool = true
objOne := gvar.New(ok, true)
gtest.Assert(objOne.Bool(), ok)
t.Assert(objOne.Bool(), ok)
ok = false
objTwo := gvar.New(ok, true)
gtest.Assert(objTwo.Bool(), ok)
t.Assert(objTwo.Bool(), ok)
})
}
func Test_Int(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var num int = 1
objOne := gvar.New(num, true)
gtest.Assert(objOne.Int(), num)
t.Assert(objOne.Int(), num)
})
}
func Test_Int8(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var num int8 = 1
objOne := gvar.New(num, true)
gtest.Assert(objOne.Int8(), num)
t.Assert(objOne.Int8(), num)
})
}
func Test_Int16(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var num int16 = 1
objOne := gvar.New(num, true)
gtest.Assert(objOne.Int16(), num)
t.Assert(objOne.Int16(), num)
})
}
func Test_Int32(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var num int32 = 1
objOne := gvar.New(num, true)
gtest.Assert(objOne.Int32(), num)
t.Assert(objOne.Int32(), num)
})
}
func Test_Int64(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var num int64 = 1
objOne := gvar.New(num, true)
gtest.Assert(objOne.Int64(), num)
t.Assert(objOne.Int64(), num)
})
}
func Test_Uint(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var num uint = 1
objOne := gvar.New(num, true)
gtest.Assert(objOne.Uint(), num)
t.Assert(objOne.Uint(), num)
})
}
func Test_Uint8(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var num uint8 = 1
objOne := gvar.New(num, true)
gtest.Assert(objOne.Uint8(), num)
t.Assert(objOne.Uint8(), num)
})
}
func Test_Uint16(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var num uint16 = 1
objOne := gvar.New(num, true)
gtest.Assert(objOne.Uint16(), num)
t.Assert(objOne.Uint16(), num)
})
}
func Test_Uint32(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var num uint32 = 1
objOne := gvar.New(num, true)
gtest.Assert(objOne.Uint32(), num)
t.Assert(objOne.Uint32(), num)
})
}
func Test_Uint64(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var num uint64 = 1
objOne := gvar.New(num, true)
gtest.Assert(objOne.Uint64(), num)
t.Assert(objOne.Uint64(), num)
})
}
func Test_Float32(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var num float32 = 1.1
objOne := gvar.New(num, true)
gtest.Assert(objOne.Float32(), num)
t.Assert(objOne.Float32(), num)
})
}
func Test_Float64(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var num float64 = 1.1
objOne := gvar.New(num, true)
gtest.Assert(objOne.Float64(), num)
t.Assert(objOne.Float64(), num)
})
}
func Test_Ints(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, true)
gtest.Assert(objOne.Ints()[0], arr[0])
t.Assert(objOne.Ints()[0], arr[0])
})
}
func Test_Floats(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var arr = []float64{1, 2, 3, 4, 5}
objOne := gvar.New(arr, true)
gtest.Assert(objOne.Floats()[0], arr[0])
t.Assert(objOne.Floats()[0], arr[0])
})
}
func Test_Strings(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var arr = []string{"hello", "world"}
objOne := gvar.New(arr, true)
gtest.Assert(objOne.Strings()[0], arr[0])
t.Assert(objOne.Strings()[0], arr[0])
})
}
func Test_Interfaces(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, true)
gtest.Assert(objOne.Interfaces(), arr)
t.Assert(objOne.Interfaces(), arr)
})
}
func Test_Slice(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, true)
gtest.Assert(objOne.Slice(), arr)
t.Assert(objOne.Slice(), arr)
})
}
func Test_Array(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, false)
gtest.Assert(objOne.Array(), arr)
t.Assert(objOne.Array(), arr)
})
}
func Test_Vars(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var arr = []int{1, 2, 3, 4, 5}
objOne := gvar.New(arr, false)
gtest.Assert(len(objOne.Vars()), 5)
gtest.Assert(objOne.Vars()[0].Int(), 1)
gtest.Assert(objOne.Vars()[4].Int(), 5)
t.Assert(len(objOne.Vars()), 5)
t.Assert(objOne.Vars()[0].Int(), 1)
t.Assert(objOne.Vars()[4].Int(), 5)
})
}
func Test_Time(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var timeUnix int64 = 1556242660
objOne := gvar.New(timeUnix, true)
gtest.Assert(objOne.Time().Unix(), timeUnix)
t.Assert(objOne.Time().Unix(), timeUnix)
})
}
func Test_GTime(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var timeUnix int64 = 1556242660
objOne := gvar.New(timeUnix, true)
gtest.Assert(objOne.GTime().Unix(), timeUnix)
t.Assert(objOne.GTime().Unix(), timeUnix)
})
}
func Test_Duration(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var timeUnix int64 = 1556242660
objOne := gvar.New(timeUnix, true)
gtest.Assert(objOne.Duration(), time.Duration(timeUnix))
t.Assert(objOne.Duration(), time.Duration(timeUnix))
})
}
func Test_Map(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
m := g.Map{
"k1": "v1",
"k2": "v2",
}
objOne := gvar.New(m, true)
gtest.Assert(objOne.Map()["k1"], m["k1"])
gtest.Assert(objOne.Map()["k2"], m["k2"])
t.Assert(objOne.Map()["k1"], m["k1"])
t.Assert(objOne.Map()["k2"], m["k2"])
})
}
func Test_Struct(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
type StTest struct {
Test int
}
@ -332,67 +332,76 @@ func Test_Struct(t *testing.T) {
objOne.Struct(testObj)
gtest.Assert(testObj.Test, Kv["Test"])
t.Assert(testObj.Test, Kv["Test"])
})
gtest.C(t, func(t *gtest.T) {
type StTest struct {
Test int8
}
o := &StTest{}
v := gvar.New(g.Slice{"Test", "-25"})
v.Struct(o)
t.Assert(o.Test, -25)
})
}
func Test_Json(t *testing.T) {
// Marshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := "i love gf"
v := gvar.New(s)
b1, err1 := json.Marshal(v)
b2, err2 := json.Marshal(s)
gtest.Assert(err1, err2)
gtest.Assert(b1, b2)
t.Assert(err1, err2)
t.Assert(b1, b2)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := int64(math.MaxInt64)
v := gvar.New(s)
b1, err1 := json.Marshal(v)
b2, err2 := json.Marshal(s)
gtest.Assert(err1, err2)
gtest.Assert(b1, b2)
t.Assert(err1, err2)
t.Assert(b1, b2)
})
// Unmarshal
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := "i love gf"
v := gvar.New(nil)
b, err := json.Marshal(s)
gtest.Assert(err, nil)
t.Assert(err, nil)
err = json.Unmarshal(b, v)
gtest.Assert(err, nil)
gtest.Assert(v.String(), s)
t.Assert(err, nil)
t.Assert(v.String(), s)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var v gvar.Var
s := "i love gf"
b, err := json.Marshal(s)
gtest.Assert(err, nil)
t.Assert(err, nil)
err = json.Unmarshal(b, &v)
gtest.Assert(err, nil)
gtest.Assert(v.String(), s)
t.Assert(err, nil)
t.Assert(v.String(), s)
})
}
func Test_UnmarshalValue(t *testing.T) {
type T struct {
type V struct {
Name string
Var *gvar.Var
}
gtest.Case(t, func() {
var t *T
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"var": "v",
}, &t)
gtest.Assert(err, nil)
gtest.Assert(t.Name, "john")
gtest.Assert(t.Var.String(), "v")
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Var.String(), "v")
})
}

View File

@ -40,111 +40,111 @@ var (
)
func TestEncrypt(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
data, err := gaes.Encrypt(content, key_16)
gtest.Assert(err, nil)
gtest.Assert(data, []byte(content_16))
t.Assert(err, nil)
t.Assert(data, []byte(content_16))
data, err = gaes.Encrypt(content, key_24)
gtest.Assert(err, nil)
gtest.Assert(data, []byte(content_24))
t.Assert(err, nil)
t.Assert(data, []byte(content_24))
data, err = gaes.Encrypt(content, key_32)
gtest.Assert(err, nil)
gtest.Assert(data, []byte(content_32))
t.Assert(err, nil)
t.Assert(data, []byte(content_32))
data, err = gaes.Encrypt(content, key_16, iv)
gtest.Assert(err, nil)
gtest.Assert(data, []byte(content_16_iv))
t.Assert(err, nil)
t.Assert(data, []byte(content_16_iv))
data, err = gaes.Encrypt(content, key_32, iv)
gtest.Assert(err, nil)
gtest.Assert(data, []byte(content_32_iv))
t.Assert(err, nil)
t.Assert(data, []byte(content_32_iv))
})
}
func TestDecrypt(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
decrypt, err := gaes.Decrypt([]byte(content_16), key_16)
gtest.Assert(err, nil)
gtest.Assert(decrypt, content)
t.Assert(err, nil)
t.Assert(decrypt, content)
decrypt, err = gaes.Decrypt([]byte(content_24), key_24)
gtest.Assert(err, nil)
gtest.Assert(decrypt, content)
t.Assert(err, nil)
t.Assert(decrypt, content)
decrypt, err = gaes.Decrypt([]byte(content_32), key_32)
gtest.Assert(err, nil)
gtest.Assert(decrypt, content)
t.Assert(err, nil)
t.Assert(decrypt, content)
decrypt, err = gaes.Decrypt([]byte(content_16_iv), key_16, iv)
gtest.Assert(err, nil)
gtest.Assert(decrypt, content)
t.Assert(err, nil)
t.Assert(decrypt, content)
decrypt, err = gaes.Decrypt([]byte(content_32_iv), key_32, iv)
gtest.Assert(err, nil)
gtest.Assert(decrypt, content)
t.Assert(err, nil)
t.Assert(decrypt, content)
decrypt, err = gaes.Decrypt([]byte(content_32_iv), keys, iv)
gtest.Assert(err, "invalid padding")
t.Assert(err, "invalid padding")
})
}
func TestEncryptErr(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
// encrypt key error
_, err := gaes.Encrypt(content, key_err)
gtest.AssertNE(err, nil)
t.AssertNE(err, nil)
})
}
func TestDecryptErr(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
// decrypt key error
encrypt, err := gaes.Encrypt(content, key_16)
_, err = gaes.Decrypt(encrypt, key_err)
gtest.AssertNE(err, nil)
t.AssertNE(err, nil)
// decrypt content too short error
_, err = gaes.Decrypt([]byte("test"), key_16)
gtest.AssertNE(err, nil)
t.AssertNE(err, nil)
// decrypt content size error
_, err = gaes.Decrypt(key_17, key_16)
gtest.AssertNE(err, nil)
t.AssertNE(err, nil)
})
}
func TestPKCS5UnPaddingErr(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
// PKCS5UnPadding blockSize zero
_, err := gaes.PKCS5UnPadding(content, 0)
gtest.AssertNE(err, nil)
t.AssertNE(err, nil)
// PKCS5UnPadding src len zero
_, err = gaes.PKCS5UnPadding([]byte(""), 16)
gtest.AssertNE(err, nil)
t.AssertNE(err, nil)
// PKCS5UnPadding src len > blockSize
_, err = gaes.PKCS5UnPadding(key_17, 16)
gtest.AssertNE(err, nil)
t.AssertNE(err, nil)
// PKCS5UnPadding src len > blockSize
_, err = gaes.PKCS5UnPadding(key_32_err, 32)
gtest.AssertNE(err, nil)
t.AssertNE(err, nil)
})
}
func TestEncryptCFB(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
var padding int = 0
data, err := gaes.EncryptCFB(content, key_16, &padding, iv)
gtest.Assert(err, nil)
gtest.Assert(padding, padding_size)
gtest.Assert(data, []byte(content_16_cfb))
t.Assert(err, nil)
t.Assert(padding, padding_size)
t.Assert(data, []byte(content_16_cfb))
})
}
func TestDecryptCFB(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
decrypt, err := gaes.DecryptCFB([]byte(content_16_cfb), key_16, padding_size, iv)
gtest.Assert(err, nil)
gtest.Assert(decrypt, content)
t.Assert(err, nil)
t.Assert(decrypt, content)
})
}

View File

@ -17,17 +17,17 @@ import (
)
func TestEncrypt(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
s := "pibigstar"
result := 693191136
encrypt1 := gcrc32.Encrypt(s)
encrypt2 := gcrc32.Encrypt([]byte(s))
gtest.AssertEQ(int(encrypt1), result)
gtest.AssertEQ(int(encrypt2), result)
t.AssertEQ(int(encrypt1), result)
t.AssertEQ(int(encrypt2), result)
strmd5, _ := gmd5.Encrypt(s)
test1 := gcrc32.Encrypt(strmd5)
test2 := gcrc32.Encrypt([]byte(strmd5))
gtest.AssertEQ(test2, test1)
t.AssertEQ(test2, test1)
})
}

View File

@ -21,81 +21,81 @@ var (
)
func TestDesECB(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
key := []byte("11111111")
text := []byte("12345678")
padding := gdes.NOPADDING
result := "858b176da8b12503"
// encrypt test
cipherText, err := gdes.EncryptECB(text, key, padding)
gtest.AssertEQ(err, nil)
gtest.AssertEQ(hex.EncodeToString(cipherText), result)
t.AssertEQ(err, nil)
t.AssertEQ(hex.EncodeToString(cipherText), result)
// decrypt test
clearText, err := gdes.DecryptECB(cipherText, key, padding)
gtest.AssertEQ(err, nil)
gtest.AssertEQ(string(clearText), "12345678")
t.AssertEQ(err, nil)
t.AssertEQ(string(clearText), "12345678")
// encrypt err test. when throw exception,the err is not equal nil and the string is nil
errEncrypt, err := gdes.EncryptECB(text, key, errPadding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errEncrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errEncrypt, nil)
errEncrypt, err = gdes.EncryptECB(text, errKey, padding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errEncrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errEncrypt, nil)
// err decrypt test.
errDecrypt, err := gdes.DecryptECB(cipherText, errKey, padding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errDecrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errDecrypt, nil)
errDecrypt, err = gdes.DecryptECB(cipherText, key, errPadding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errDecrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errDecrypt, nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
key := []byte("11111111")
text := []byte("12345678")
padding := gdes.PKCS5PADDING
errPadding := 5
result := "858b176da8b12503ad6a88b4fa37833d"
cipherText, err := gdes.EncryptECB(text, key, padding)
gtest.AssertEQ(err, nil)
gtest.AssertEQ(hex.EncodeToString(cipherText), result)
t.AssertEQ(err, nil)
t.AssertEQ(hex.EncodeToString(cipherText), result)
// decrypt test
clearText, err := gdes.DecryptECB(cipherText, key, padding)
gtest.AssertEQ(err, nil)
gtest.AssertEQ(string(clearText), "12345678")
t.AssertEQ(err, nil)
t.AssertEQ(string(clearText), "12345678")
// err test
errEncrypt, err := gdes.EncryptECB(text, key, errPadding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errEncrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errEncrypt, nil)
errDecrypt, err := gdes.DecryptECB(cipherText, errKey, padding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errDecrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errDecrypt, nil)
})
}
func Test3DesECB(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
key := []byte("1111111111111234")
text := []byte("1234567812345678")
padding := gdes.NOPADDING
result := "a23ee24b98c26263a23ee24b98c26263"
// encrypt test
cipherText, err := gdes.EncryptECBTriple(text, key, padding)
gtest.AssertEQ(err, nil)
gtest.AssertEQ(hex.EncodeToString(cipherText), result)
t.AssertEQ(err, nil)
t.AssertEQ(hex.EncodeToString(cipherText), result)
// decrypt test
clearText, err := gdes.DecryptECBTriple(cipherText, key, padding)
gtest.AssertEQ(err, nil)
gtest.AssertEQ(string(clearText), "1234567812345678")
t.AssertEQ(err, nil)
t.AssertEQ(string(clearText), "1234567812345678")
// err test
errEncrypt, err := gdes.EncryptECB(text, key, errPadding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errEncrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errEncrypt, nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
key := []byte("111111111111123412345678")
text := []byte("123456789")
padding := gdes.PKCS5PADDING
@ -103,29 +103,29 @@ func Test3DesECB(t *testing.T) {
result := "37989b1effc07a6d00ff89a7d052e79f"
// encrypt test
cipherText, err := gdes.EncryptECBTriple(text, key, padding)
gtest.AssertEQ(err, nil)
gtest.AssertEQ(hex.EncodeToString(cipherText), result)
t.AssertEQ(err, nil)
t.AssertEQ(hex.EncodeToString(cipherText), result)
// decrypt test
clearText, err := gdes.DecryptECBTriple(cipherText, key, padding)
gtest.AssertEQ(err, nil)
gtest.AssertEQ(string(clearText), "123456789")
t.AssertEQ(err, nil)
t.AssertEQ(string(clearText), "123456789")
// err test, when key is err, but text and padding is right
errEncrypt, err := gdes.EncryptECBTriple(text, errKey, padding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errEncrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errEncrypt, nil)
// when padding is err,but key and text is right
errEncrypt, err = gdes.EncryptECBTriple(text, key, errPadding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errEncrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errEncrypt, nil)
// decrypt err test,when key is err
errEncrypt, err = gdes.DecryptECBTriple(text, errKey, padding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errEncrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errEncrypt, nil)
})
}
func TestDesCBC(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
key := []byte("11111111")
text := []byte("1234567812345678")
padding := gdes.NOPADDING
@ -133,39 +133,39 @@ func TestDesCBC(t *testing.T) {
result := "40826a5800608c87585ca7c9efabee47"
// encrypt test
cipherText, err := gdes.EncryptCBC(text, key, iv, padding)
gtest.AssertEQ(err, nil)
gtest.AssertEQ(hex.EncodeToString(cipherText), result)
t.AssertEQ(err, nil)
t.AssertEQ(hex.EncodeToString(cipherText), result)
// decrypt test
clearText, err := gdes.DecryptCBC(cipherText, key, iv, padding)
gtest.AssertEQ(err, nil)
gtest.AssertEQ(string(clearText), "1234567812345678")
t.AssertEQ(err, nil)
t.AssertEQ(string(clearText), "1234567812345678")
// encrypt err test.
errEncrypt, err := gdes.EncryptCBC(text, errKey, iv, padding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errEncrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errEncrypt, nil)
// the iv is err
errEncrypt, err = gdes.EncryptCBC(text, key, errIv, padding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errEncrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errEncrypt, nil)
// the padding is err
errEncrypt, err = gdes.EncryptCBC(text, key, iv, errPadding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errEncrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errEncrypt, nil)
// decrypt err test. the key is err
errDecrypt, err := gdes.DecryptCBC(cipherText, errKey, iv, padding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errDecrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errDecrypt, nil)
// the iv is err
errDecrypt, err = gdes.DecryptCBC(cipherText, key, errIv, padding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errDecrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errDecrypt, nil)
// the padding is err
errDecrypt, err = gdes.DecryptCBC(cipherText, key, iv, errPadding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errDecrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errDecrypt, nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
key := []byte("11111111")
text := []byte("12345678")
padding := gdes.PKCS5PADDING
@ -173,21 +173,21 @@ func TestDesCBC(t *testing.T) {
result := "40826a5800608c87100a25d86ac7c52c"
// encrypt test
cipherText, err := gdes.EncryptCBC(text, key, iv, padding)
gtest.AssertEQ(err, nil)
gtest.AssertEQ(hex.EncodeToString(cipherText), result)
t.AssertEQ(err, nil)
t.AssertEQ(hex.EncodeToString(cipherText), result)
// decrypt test
clearText, err := gdes.DecryptCBC(cipherText, key, iv, padding)
gtest.AssertEQ(err, nil)
gtest.AssertEQ(string(clearText), "12345678")
t.AssertEQ(err, nil)
t.AssertEQ(string(clearText), "12345678")
// err test
errEncrypt, err := gdes.EncryptCBC(text, key, errIv, padding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errEncrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errEncrypt, nil)
})
}
func Test3DesCBC(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
key := []byte("1111111112345678")
text := []byte("1234567812345678")
padding := gdes.NOPADDING
@ -195,38 +195,38 @@ func Test3DesCBC(t *testing.T) {
result := "bfde1394e265d5f738d5cab170c77c88"
// encrypt test
cipherText, err := gdes.EncryptCBCTriple(text, key, iv, padding)
gtest.AssertEQ(err, nil)
gtest.AssertEQ(hex.EncodeToString(cipherText), result)
t.AssertEQ(err, nil)
t.AssertEQ(hex.EncodeToString(cipherText), result)
// decrypt test
clearText, err := gdes.DecryptCBCTriple(cipherText, key, iv, padding)
gtest.AssertEQ(err, nil)
gtest.AssertEQ(string(clearText), "1234567812345678")
t.AssertEQ(err, nil)
t.AssertEQ(string(clearText), "1234567812345678")
// encrypt err test
errEncrypt, err := gdes.EncryptCBCTriple(text, errKey, iv, padding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errEncrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errEncrypt, nil)
// the iv is err
errEncrypt, err = gdes.EncryptCBCTriple(text, key, errIv, padding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errEncrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errEncrypt, nil)
// the padding is err
errEncrypt, err = gdes.EncryptCBCTriple(text, key, iv, errPadding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errEncrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errEncrypt, nil)
// decrypt err test
errDecrypt, err := gdes.DecryptCBCTriple(cipherText, errKey, iv, padding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errDecrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errDecrypt, nil)
// the iv is err
errDecrypt, err = gdes.DecryptCBCTriple(cipherText, key, errIv, padding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errDecrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errDecrypt, nil)
// the padding is err
errDecrypt, err = gdes.DecryptCBCTriple(cipherText, key, iv, errPadding)
gtest.AssertNE(err, nil)
gtest.AssertEQ(errDecrypt, nil)
t.AssertNE(err, nil)
t.AssertEQ(errDecrypt, nil)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
key := []byte("111111111234567812345678")
text := []byte("12345678")
padding := gdes.PKCS5PADDING
@ -234,12 +234,12 @@ func Test3DesCBC(t *testing.T) {
result := "40826a5800608c87100a25d86ac7c52c"
// encrypt test
cipherText, err := gdes.EncryptCBCTriple(text, key, iv, padding)
gtest.AssertEQ(err, nil)
gtest.AssertEQ(hex.EncodeToString(cipherText), result)
t.AssertEQ(err, nil)
t.AssertEQ(hex.EncodeToString(cipherText), result)
// decrypt test
clearText, err := gdes.DecryptCBCTriple(cipherText, key, iv, padding)
gtest.AssertEQ(err, nil)
gtest.AssertEQ(string(clearText), "12345678")
t.AssertEQ(err, nil)
t.AssertEQ(string(clearText), "12345678")
})
}

View File

@ -29,16 +29,16 @@ type user struct {
}
func TestEncrypt(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
encryptString, _ := gmd5.Encrypt(s)
gtest.Assert(encryptString, result)
t.Assert(encryptString, result)
result := "1427562bb29f88a1161590b76398ab72"
encrypt, _ := gmd5.Encrypt(123456)
gtest.AssertEQ(encrypt, result)
t.AssertEQ(encrypt, result)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
user := &user{
name: "派大星",
password: "123456",
@ -46,14 +46,14 @@ func TestEncrypt(t *testing.T) {
}
result := "70917ebce8bd2f78c736cda63870fb39"
encrypt, _ := gmd5.Encrypt(user)
gtest.AssertEQ(encrypt, result)
t.AssertEQ(encrypt, result)
})
}
func TestEncryptString(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
encryptString, _ := gmd5.EncryptString(s)
gtest.Assert(encryptString, result)
t.Assert(encryptString, result)
})
}
@ -61,17 +61,17 @@ func TestEncryptFile(t *testing.T) {
path := "test.text"
errorPath := "err.txt"
result := "e6e6e1cd41895beebff16d5452dfce12"
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
file, err := os.Create(path)
defer os.Remove(path)
defer file.Close()
gtest.Assert(err, nil)
t.Assert(err, nil)
_, _ = file.Write([]byte("Hello Go Frame"))
encryptFile, _ := gmd5.EncryptFile(path)
gtest.AssertEQ(encryptFile, result)
t.AssertEQ(encryptFile, result)
// when the file is not exist,encrypt will return empty string
errEncrypt, _ := gmd5.EncryptFile(errorPath)
gtest.AssertEQ(errEncrypt, "")
t.AssertEQ(errEncrypt, "")
})
}

View File

@ -23,7 +23,7 @@ type user struct {
}
func TestEncrypt(t *testing.T) {
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
user := &user{
name: "派大星",
password: "123456",
@ -31,29 +31,29 @@ func TestEncrypt(t *testing.T) {
}
result := "97386736e3ee4adee5ca595c78c12129f6032cad"
encrypt := gsha1.Encrypt(user)
gtest.AssertEQ(encrypt, result)
t.AssertEQ(encrypt, result)
})
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
result := "5b4c1c2a08ca85ddd031ef8627414f4cb2620b41"
s := gsha1.Encrypt("pibigstar")
gtest.AssertEQ(s, result)
t.AssertEQ(s, result)
})
}
func TestEncryptFile(t *testing.T) {
path := "test.text"
errPath := "err.text"
gtest.Case(t, func() {
gtest.C(t, func(t *gtest.T) {
result := "8b05d3ba24b8d2374b8f5149d9f3fbada14ea984"
file, err := os.Create(path)
defer os.Remove(path)
defer file.Close()
gtest.Assert(err, nil)
t.Assert(err, nil)
_, _ = file.Write([]byte("Hello Go Frame"))
encryptFile, _ := gsha1.EncryptFile(path)
gtest.AssertEQ(encryptFile, result)
t.AssertEQ(encryptFile, result)
// when the file is not exist,encrypt will return empty string
errEncrypt, _ := gsha1.EncryptFile(errPath)
gtest.AssertEQ(errEncrypt, "")
t.AssertEQ(errEncrypt, "")
})
}

View File

@ -11,6 +11,7 @@ import (
"database/sql"
"errors"
"fmt"
"github.com/gogf/gf/internal/intlog"
"time"
"github.com/gogf/gf/os/glog"
@ -22,41 +23,42 @@ import (
"github.com/gogf/gf/util/grand"
)
// DB is the interface for ORM operations.
// DB defines the interfaces for ORM operations.
type DB interface {
// Open creates a raw connection object for database with given node configuration.
// Note that it is not recommended using the this function manually.
Open(config *ConfigNode) (*sql.DB, error)
// Query APIs.
Query(query string, args ...interface{}) (*sql.Rows, error)
Query(sql string, args ...interface{}) (*sql.Rows, error)
Exec(sql string, args ...interface{}) (sql.Result, error)
Prepare(sql string, execOnMaster ...bool) (*sql.Stmt, error)
// Internal APIs for CURD, which can be overwrote for custom CURD implements.
doQuery(link dbLink, query string, args ...interface{}) (rows *sql.Rows, err error)
doGetAll(link dbLink, query string, args ...interface{}) (result Result, err error)
doExec(link dbLink, query string, args ...interface{}) (result sql.Result, err error)
doPrepare(link dbLink, query string) (*sql.Stmt, error)
doInsert(link dbLink, table string, data interface{}, option int, batch ...int) (result sql.Result, err error)
doBatchInsert(link dbLink, table string, list interface{}, option int, batch ...int) (result sql.Result, err error)
doUpdate(link dbLink, table string, data interface{}, condition string, args ...interface{}) (result sql.Result, err error)
doDelete(link dbLink, table string, condition string, args ...interface{}) (result sql.Result, err error)
DoQuery(link Link, sql string, args ...interface{}) (rows *sql.Rows, err error)
DoGetAll(link Link, sql string, args ...interface{}) (result Result, err error)
DoExec(link Link, sql string, args ...interface{}) (result sql.Result, err error)
DoPrepare(link Link, sql string) (*sql.Stmt, error)
DoInsert(link Link, table string, data interface{}, option int, batch ...int) (result sql.Result, err error)
DoBatchInsert(link Link, table string, list interface{}, option int, batch ...int) (result sql.Result, err error)
DoUpdate(link Link, table string, data interface{}, condition string, args ...interface{}) (result sql.Result, err error)
DoDelete(link Link, table string, condition string, args ...interface{}) (result sql.Result, err error)
// Query APIs for convenience purpose.
GetAll(query string, args ...interface{}) (Result, error)
GetOne(query string, args ...interface{}) (Record, error)
GetValue(query string, args ...interface{}) (Value, error)
GetCount(query string, args ...interface{}) (int, error)
GetStruct(objPointer interface{}, query string, args ...interface{}) error
GetStructs(objPointerSlice interface{}, query string, args ...interface{}) error
GetScan(objPointer interface{}, query string, args ...interface{}) error
GetAll(sql string, args ...interface{}) (Result, error)
GetOne(sql string, args ...interface{}) (Record, error)
GetValue(sql string, args ...interface{}) (Value, error)
GetArray(sql string, args ...interface{}) ([]Value, error)
GetCount(sql string, args ...interface{}) (int, error)
GetStruct(objPointer interface{}, sql string, args ...interface{}) error
GetStructs(objPointerSlice interface{}, sql string, args ...interface{}) error
GetScan(objPointer interface{}, sql string, args ...interface{}) error
// Master/Slave support.
// Master/Slave specification support.
Master() (*sql.DB, error)
Slave() (*sql.DB, error)
// Ping.
// Ping-Pong.
PingMaster() error
PingSlave() error
@ -75,48 +77,49 @@ type DB interface {
Update(table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error)
Delete(table string, condition interface{}, args ...interface{}) (sql.Result, error)
// Create model.
// Model creation.
From(tables string) *Model
Table(tables string) *Model
Schema(schema string) *Schema
// Configuration methods.
GetCache() *gcache.Cache
SetDebug(debug bool)
GetDebug() bool
SetSchema(schema string)
GetSchema() string
GetPrefix() string
SetLogger(logger *glog.Logger)
GetLogger() *glog.Logger
SetMaxIdleConnCount(n int)
SetMaxOpenConnCount(n int)
SetMaxConnLifetime(d time.Duration)
// Utility methods.
GetChars() (charLeft string, charRight string)
GetMaster(schema ...string) (*sql.DB, error)
GetSlave(schema ...string) (*sql.DB, error)
QuoteWord(s string) string
QuoteString(s string) string
QuotePrefixTableName(table string) string
Tables(schema ...string) (tables []string, err error)
TableFields(table string, schema ...string) (map[string]*TableField, error)
// HandleSqlBeforeCommit is a hook function, which deals with the sql string before
// it's committed to underlying driver. The parameter <link> specifies the current
// database connection operation object. You can modify the sql string <sql> and its
// arguments <args> as you wish before they're committed to driver.
HandleSqlBeforeCommit(link Link, sql string, args []interface{}) (string, []interface{})
// Internal methods.
getCache() *gcache.Cache
getChars() (charLeft string, charRight string)
getDebug() bool
getPrefix() string
getMaster(schema ...string) (*sql.DB, error)
getSlave(schema ...string) (*sql.DB, error)
quoteWord(s string) string
quoteString(s string) string
handleTableName(table string) string
filterFields(schema, table string, data map[string]interface{}) map[string]interface{}
convertValue(fieldValue []byte, fieldType string) interface{}
rowsToResult(rows *sql.Rows) (Result, error)
handleSqlBeforeExec(sql string) string
}
// dbLink is a common database function wrapper interface for internal usage.
type dbLink interface {
Query(query string, args ...interface{}) (*sql.Rows, error)
Exec(sql string, args ...interface{}) (sql.Result, error)
Prepare(sql string) (*sql.Stmt, error)
}
// dbBase is the base struct for database management.
type dbBase struct {
db DB // DB interface object.
// Core is the base struct for database management.
type Core struct {
DB DB // DB interface object.
group string // Configuration group name.
debug *gtype.Bool // Enable debug mode for the database.
cache *gcache.Cache // Cache manager.
@ -128,6 +131,12 @@ type dbBase struct {
maxConnLifetime time.Duration // Max TTL for a connection.
}
// Driver is the interface for integrating sql drivers into package gdb.
type Driver interface {
// New creates and returns a database object for specified database server.
New(core *Core, node *ConfigNode) (DB, error)
}
// Sql is the sql recording struct.
type Sql struct {
Sql string // SQL string(may contain reserved char '?').
@ -150,6 +159,13 @@ type TableField struct {
Comment string // Comment.
}
// Link is a common database function wrapper interface.
type Link interface {
Query(sql string, args ...interface{}) (*sql.Rows, error)
Exec(sql string, args ...interface{}) (sql.Result, error)
Prepare(sql string) (*sql.Stmt, error)
}
// Value is the field value type.
type Value = *gvar.Var
@ -167,19 +183,36 @@ type Map = map[string]interface{}
type List = []Map
const (
gINSERT_OPTION_DEFAULT = 0
gINSERT_OPTION_REPLACE = 1
gINSERT_OPTION_SAVE = 2
gINSERT_OPTION_IGNORE = 3
gDEFAULT_BATCH_NUM = 10 // Per count for batch insert/replace/save
gDEFAULT_CONN_MAX_LIFE_TIME = 30 // Max life time for per connection in pool in seconds.
gINSERT_OPTION_DEFAULT = 0
gINSERT_OPTION_REPLACE = 1
gINSERT_OPTION_SAVE = 2
gINSERT_OPTION_IGNORE = 3
gDEFAULT_BATCH_NUM = 10 // Per count for batch insert/replace/save
gDEFAULT_CONN_MAX_IDLE_COUNT = 10 // Max idle connection count in pool.
gDEFAULT_CONN_MAX_LIFE_TIME = 30 // Max life time for per connection in pool in seconds.
)
var (
// Instance map.
// ErrNoRows is alias of sql.ErrNoRows.
ErrNoRows = sql.ErrNoRows
// instances is the management map for instances.
instances = gmap.NewStrAnyMap(true)
// driverMap manages all custom registered driver.
driverMap = map[string]Driver{
"mysql": &DriverMysql{},
"mssql": &DriverMssql{},
"pgsql": &DriverPgsql{},
"oracle": &DriverOracle{},
"sqlite": &DriverSqlite{},
}
)
// Register registers custom database driver to gdb.
func Register(name string, driver Driver) error {
driverMap[name] = driver
return nil
}
// New creates and returns an ORM object with global configurations.
// The parameter <name> specifies the configuration group name,
// which is DEFAULT_GROUP_NAME in default.
@ -196,31 +229,25 @@ func New(name ...string) (db DB, err error) {
}
if _, ok := configs.config[group]; ok {
if node, err := getConfigNodeByGroup(group, true); err == nil {
base := &dbBase{
group: group,
debug: gtype.NewBool(),
cache: gcache.New(),
schema: gtype.NewString(),
logger: glog.New(),
prefix: node.Prefix,
// Default max connection life time if user does not configure.
maxConnLifetime: gDEFAULT_CONN_MAX_LIFE_TIME,
c := &Core{
group: group,
debug: gtype.NewBool(),
cache: gcache.New(),
schema: gtype.NewString(),
logger: glog.New(),
prefix: node.Prefix,
maxIdleConnCount: gDEFAULT_CONN_MAX_IDLE_COUNT,
maxConnLifetime: gDEFAULT_CONN_MAX_LIFE_TIME, // Default max connection life time if user does not configure.
}
switch node.Type {
case "mysql":
base.db = &dbMysql{dbBase: base}
case "pgsql":
base.db = &dbPgsql{dbBase: base}
case "mssql":
base.db = &dbMssql{dbBase: base}
case "sqlite":
base.db = &dbSqlite{dbBase: base}
case "oracle":
base.db = &dbOracle{dbBase: base}
default:
if v, ok := driverMap[node.Type]; ok {
c.DB, err = v.New(c, node)
if err != nil {
return nil, err
}
return c.DB, nil
} else {
return nil, errors.New(fmt.Sprintf(`unsupported database type "%s"`, node.Type))
}
return base.db, nil
} else {
return nil, err
}
@ -321,9 +348,9 @@ func getConfigNodeByWeight(cg ConfigGroup) *ConfigNode {
// getSqlDb retrieves and returns a underlying database connection object.
// The parameter <master> specifies whether retrieves master node connection if
// master-slave nodes are configured.
func (bs *dbBase) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err error) {
func (c *Core) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err error) {
// Load balance.
node, err := getConfigNodeByGroup(bs.group, master)
node, err := getConfigNodeByGroup(c.group, master)
if err != nil {
return nil, err
}
@ -332,7 +359,7 @@ func (bs *dbBase) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err er
node.Charset = "utf8"
}
// Changes the schema.
nodeSchema := bs.schema.Val()
nodeSchema := c.schema.Val()
if len(schema) > 0 && schema[0] != "" {
nodeSchema = schema[0]
}
@ -342,26 +369,27 @@ func (bs *dbBase) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err er
n.Name = nodeSchema
node = &n
}
// Cache the underlying connection object by node.
v := bs.cache.GetOrSetFuncLock(node.String(), func() interface{} {
sqlDb, err = bs.db.Open(node)
// Cache the underlying connection pool object by node.
v := c.cache.GetOrSetFuncLock(node.String(), func() interface{} {
sqlDb, err = c.DB.Open(node)
if err != nil {
intlog.Printf("DB open failed: %v, %+v", err, node)
return nil
}
if bs.maxIdleConnCount > 0 {
sqlDb.SetMaxIdleConns(bs.maxIdleConnCount)
if c.maxIdleConnCount > 0 {
sqlDb.SetMaxIdleConns(c.maxIdleConnCount)
} else if node.MaxIdleConnCount > 0 {
sqlDb.SetMaxIdleConns(node.MaxIdleConnCount)
}
if bs.maxOpenConnCount > 0 {
sqlDb.SetMaxOpenConns(bs.maxOpenConnCount)
if c.maxOpenConnCount > 0 {
sqlDb.SetMaxOpenConns(c.maxOpenConnCount)
} else if node.MaxOpenConnCount > 0 {
sqlDb.SetMaxOpenConns(node.MaxOpenConnCount)
}
if bs.maxConnLifetime > 0 {
sqlDb.SetConnMaxLifetime(bs.maxConnLifetime * time.Second)
if c.maxConnLifetime > 0 {
sqlDb.SetConnMaxLifetime(c.maxConnLifetime * time.Second)
} else if node.MaxConnLifetime > 0 {
sqlDb.SetConnMaxLifetime(node.MaxConnLifetime * time.Second)
}
@ -371,40 +399,7 @@ func (bs *dbBase) getSqlDb(master bool, schema ...string) (sqlDb *sql.DB, err er
sqlDb = v.(*sql.DB)
}
if node.Debug {
bs.db.SetDebug(node.Debug)
c.DB.SetDebug(node.Debug)
}
return
}
// SetSchema changes the schema for this database connection object.
// Importantly note that when schema configuration changed for the database,
// it affects all operations on the database object in the future.
func (bs *dbBase) SetSchema(schema string) {
bs.schema.Set(schema)
}
// Master creates and returns a connection from master node if master-slave configured.
// It returns the default connection if master-slave not configured.
func (bs *dbBase) Master() (*sql.DB, error) {
return bs.getSqlDb(true, bs.schema.Val())
}
// Slave creates and returns a connection from slave node if master-slave configured.
// It returns the default connection if master-slave not configured.
func (bs *dbBase) Slave() (*sql.DB, error) {
return bs.getSqlDb(false, bs.schema.Val())
}
// getMaster acts like function Master but with additional <schema> parameter specifying
// the schema for the connection. It is defined for internal usage.
// Also see Master.
func (bs *dbBase) getMaster(schema ...string) (*sql.DB, error) {
return bs.getSqlDb(true, schema...)
}
// getSlave acts like function Slave but with additional <schema> parameter specifying
// the schema for the connection. It is defined for internal usage.
// Also see Slave.
func (bs *dbBase) getSlave(schema ...string) (*sql.DB, error) {
return bs.getSqlDb(false, schema...)
}

View File

@ -1,25 +0,0 @@
// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gdb
import "database/sql"
// batchSqlResult is execution result for batch operations.
type batchSqlResult struct {
rowsAffected int64
lastResult sql.Result
}
// see sql.Result.RowsAffected
func (r *batchSqlResult) RowsAffected() (int64, error) {
return r.rowsAffected, nil
}
// see sql.Result.LastInsertId
func (r *batchSqlResult) LastInsertId() (int64, error) {
return r.lastResult.LastInsertId()
}

View File

@ -16,7 +16,6 @@ import (
"strings"
"github.com/gogf/gf/container/gvar"
"github.com/gogf/gf/os/gcache"
"github.com/gogf/gf/os/gtime"
"github.com/gogf/gf/text/gregex"
"github.com/gogf/gf/util/gconv"
@ -32,77 +31,89 @@ var (
lastOperatorReg = regexp.MustCompile(`[<>=]+\s*$`)
)
// Master creates and returns a connection from master node if master-slave configured.
// It returns the default connection if master-slave not configured.
func (c *Core) Master() (*sql.DB, error) {
return c.getSqlDb(true, c.schema.Val())
}
// Slave creates and returns a connection from slave node if master-slave configured.
// It returns the default connection if master-slave not configured.
func (c *Core) Slave() (*sql.DB, error) {
return c.getSqlDb(false, c.schema.Val())
}
// Query commits one query SQL to underlying driver and returns the execution result.
// It is most commonly used for data querying.
func (bs *dbBase) Query(query string, args ...interface{}) (rows *sql.Rows, err error) {
link, err := bs.db.Slave()
func (c *Core) Query(sql string, args ...interface{}) (rows *sql.Rows, err error) {
link, err := c.DB.Slave()
if err != nil {
return nil, err
}
return bs.db.doQuery(link, query, args...)
return c.DB.DoQuery(link, sql, args...)
}
// doQuery commits the query string and its arguments to underlying driver
// DoQuery commits the sql string and its arguments to underlying driver
// through given link object and returns the execution result.
func (bs *dbBase) doQuery(link dbLink, query string, args ...interface{}) (rows *sql.Rows, err error) {
query, args = formatQuery(query, args)
query = bs.db.handleSqlBeforeExec(query)
if bs.db.getDebug() {
func (c *Core) DoQuery(link Link, sql string, args ...interface{}) (rows *sql.Rows, err error) {
sql, args = formatSql(sql, args)
sql, args = c.DB.HandleSqlBeforeCommit(link, sql, args)
if c.DB.GetDebug() {
mTime1 := gtime.TimestampMilli()
rows, err = link.Query(query, args...)
rows, err = link.Query(sql, args...)
mTime2 := gtime.TimestampMilli()
s := &Sql{
Sql: query,
Sql: sql,
Args: args,
Format: bindArgsToQuery(query, args),
Format: FormatSqlWithArgs(sql, args),
Error: err,
Start: mTime1,
End: mTime2,
}
bs.printSql(s)
c.writeSqlToLogger(s)
} else {
rows, err = link.Query(query, args...)
rows, err = link.Query(sql, args...)
}
if err == nil {
return rows, nil
} else {
err = formatError(err, query, args...)
err = formatError(err, sql, args...)
}
return nil, err
}
// Exec commits one query SQL to underlying driver and returns the execution result.
// It is most commonly used for data inserting and updating.
func (bs *dbBase) Exec(query string, args ...interface{}) (result sql.Result, err error) {
link, err := bs.db.Master()
func (c *Core) Exec(sql string, args ...interface{}) (result sql.Result, err error) {
link, err := c.DB.Master()
if err != nil {
return nil, err
}
return bs.db.doExec(link, query, args...)
return c.DB.DoExec(link, sql, args...)
}
// doExec commits the query string and its arguments to underlying driver
// DoExec commits the sql string and its arguments to underlying driver
// through given link object and returns the execution result.
func (bs *dbBase) doExec(link dbLink, query string, args ...interface{}) (result sql.Result, err error) {
query, args = formatQuery(query, args)
query = bs.db.handleSqlBeforeExec(query)
if bs.db.getDebug() {
func (c *Core) DoExec(link Link, sql string, args ...interface{}) (result sql.Result, err error) {
sql, args = formatSql(sql, args)
sql, args = c.DB.HandleSqlBeforeCommit(link, sql, args)
if c.DB.GetDebug() {
mTime1 := gtime.TimestampMilli()
result, err = link.Exec(query, args...)
result, err = link.Exec(sql, args...)
mTime2 := gtime.TimestampMilli()
s := &Sql{
Sql: query,
Sql: sql,
Args: args,
Format: bindArgsToQuery(query, args),
Format: FormatSqlWithArgs(sql, args),
Error: err,
Start: mTime1,
End: mTime2,
}
bs.printSql(s)
c.writeSqlToLogger(s)
} else {
result, err = link.Exec(query, args...)
result, err = link.Exec(sql, args...)
}
return result, formatError(err, query, args...)
return result, formatError(err, sql, args...)
}
// Prepare creates a prepared statement for later queries or executions.
@ -113,50 +124,50 @@ func (bs *dbBase) doExec(link dbLink, query string, args ...interface{}) (result
//
// The parameter <execOnMaster> specifies whether executing the sql on master node,
// or else it executes the sql on slave node if master-slave configured.
func (bs *dbBase) Prepare(query string, execOnMaster ...bool) (*sql.Stmt, error) {
func (c *Core) Prepare(sql string, execOnMaster ...bool) (*sql.Stmt, error) {
err := (error)(nil)
link := (dbLink)(nil)
link := (Link)(nil)
if len(execOnMaster) > 0 && execOnMaster[0] {
if link, err = bs.db.Master(); err != nil {
if link, err = c.DB.Master(); err != nil {
return nil, err
}
} else {
if link, err = bs.db.Slave(); err != nil {
if link, err = c.DB.Slave(); err != nil {
return nil, err
}
}
return bs.db.doPrepare(link, query)
return c.DB.DoPrepare(link, sql)
}
// doPrepare calls prepare function on given link object and returns the statement object.
func (bs *dbBase) doPrepare(link dbLink, query string) (*sql.Stmt, error) {
return link.Prepare(query)
func (c *Core) DoPrepare(link Link, sql string) (*sql.Stmt, error) {
return link.Prepare(sql)
}
// GetAll queries and returns data records from database.
func (bs *dbBase) GetAll(query string, args ...interface{}) (Result, error) {
return bs.db.doGetAll(nil, query, args...)
func (c *Core) GetAll(sql string, args ...interface{}) (Result, error) {
return c.DB.DoGetAll(nil, sql, args...)
}
// doGetAll queries and returns data records from database.
func (bs *dbBase) doGetAll(link dbLink, query string, args ...interface{}) (result Result, err error) {
func (c *Core) DoGetAll(link Link, sql string, args ...interface{}) (result Result, err error) {
if link == nil {
link, err = bs.db.Slave()
link, err = c.DB.Slave()
if err != nil {
return nil, err
}
}
rows, err := bs.doQuery(link, query, args...)
rows, err := c.DB.DoQuery(link, sql, args...)
if err != nil || rows == nil {
return nil, err
}
defer rows.Close()
return bs.db.rowsToResult(rows)
return c.DB.rowsToResult(rows)
}
// GetOne queries and returns one record from database.
func (bs *dbBase) GetOne(query string, args ...interface{}) (Record, error) {
list, err := bs.GetAll(query, args...)
func (c *Core) GetOne(sql string, args ...interface{}) (Record, error) {
list, err := c.DB.GetAll(sql, args...)
if err != nil {
return nil, err
}
@ -166,28 +177,38 @@ func (bs *dbBase) GetOne(query string, args ...interface{}) (Record, error) {
return nil, nil
}
// GetArray queries and returns data values as slice from database.
// Note that if there're multiple columns in the result, it returns just one column values randomly.
func (c *Core) GetArray(sql string, args ...interface{}) ([]Value, error) {
all, err := c.DB.DoGetAll(nil, sql, args...)
if err != nil {
return nil, err
}
return all.Array(), nil
}
// GetStruct queries one record from database and converts it to given struct.
// The parameter <pointer> should be a pointer to struct.
func (bs *dbBase) GetStruct(pointer interface{}, query string, args ...interface{}) error {
one, err := bs.GetOne(query, args...)
func (c *Core) GetStruct(pointer interface{}, sql string, args ...interface{}) error {
one, err := c.DB.GetOne(sql, args...)
if err != nil {
return err
}
if len(one) == 0 {
return sql.ErrNoRows
return ErrNoRows
}
return one.Struct(pointer)
}
// GetStructs queries records from database and converts them to given struct.
// The parameter <pointer> should be type of struct slice: []struct/[]*struct.
func (bs *dbBase) GetStructs(pointer interface{}, query string, args ...interface{}) error {
all, err := bs.GetAll(query, args...)
func (c *Core) GetStructs(pointer interface{}, sql string, args ...interface{}) error {
all, err := c.DB.GetAll(sql, args...)
if err != nil {
return err
}
if len(all) == 0 {
return sql.ErrNoRows
return ErrNoRows
}
return all.Structs(pointer)
}
@ -198,7 +219,7 @@ func (bs *dbBase) GetStructs(pointer interface{}, query string, args ...interfac
// If parameter <pointer> is type of struct pointer, it calls GetStruct internally for
// the conversion. If parameter <pointer> is type of slice, it calls GetStructs internally
// for conversion.
func (bs *dbBase) GetScan(pointer interface{}, query string, args ...interface{}) error {
func (c *Core) GetScan(pointer interface{}, sql string, args ...interface{}) error {
t := reflect.TypeOf(pointer)
k := t.Kind()
if k != reflect.Ptr {
@ -207,9 +228,9 @@ func (bs *dbBase) GetScan(pointer interface{}, query string, args ...interface{}
k = t.Elem().Kind()
switch k {
case reflect.Array, reflect.Slice:
return bs.db.GetStructs(pointer, query, args...)
return c.DB.GetStructs(pointer, sql, args...)
case reflect.Struct:
return bs.db.GetStruct(pointer, query, args...)
return c.DB.GetStruct(pointer, sql, args...)
}
return fmt.Errorf("element type should be type of struct/slice, unsupported: %v", k)
}
@ -217,8 +238,8 @@ func (bs *dbBase) GetScan(pointer interface{}, query string, args ...interface{}
// GetValue queries and returns the field value from database.
// The sql should queries only one field from database, or else it returns only one
// field of the result.
func (bs *dbBase) GetValue(query string, args ...interface{}) (Value, error) {
one, err := bs.GetOne(query, args...)
func (c *Core) GetValue(sql string, args ...interface{}) (Value, error) {
one, err := c.DB.GetOne(sql, args...)
if err != nil {
return nil, err
}
@ -229,13 +250,13 @@ func (bs *dbBase) GetValue(query string, args ...interface{}) (Value, error) {
}
// GetCount queries and returns the count from database.
func (bs *dbBase) GetCount(query string, args ...interface{}) (int, error) {
func (c *Core) GetCount(sql string, args ...interface{}) (int, error) {
// If the query fields do not contains function "COUNT",
// it replaces the query string and adds the "COUNT" function to the fields.
if !gregex.IsMatchString(`(?i)SELECT\s+COUNT\(.+\)\s+FROM`, query) {
query, _ = gregex.ReplaceString(`(?i)(SELECT)\s+(.+)\s+(FROM)`, `$1 COUNT($2) $3`, query)
// it replaces the sql string and adds the "COUNT" function to the fields.
if !gregex.IsMatchString(`(?i)SELECT\s+COUNT\(.+\)\s+FROM`, sql) {
sql, _ = gregex.ReplaceString(`(?i)(SELECT)\s+(.+)\s+(FROM)`, `$1 COUNT($2) $3`, sql)
}
value, err := bs.GetValue(query, args...)
value, err := c.DB.GetValue(sql, args...)
if err != nil {
return 0, err
}
@ -243,8 +264,8 @@ func (bs *dbBase) GetCount(query string, args ...interface{}) (int, error) {
}
// PingMaster pings the master node to check authentication or keeps the connection alive.
func (bs *dbBase) PingMaster() error {
if master, err := bs.db.Master(); err != nil {
func (c *Core) PingMaster() error {
if master, err := c.DB.Master(); err != nil {
return err
} else {
return master.Ping()
@ -252,8 +273,8 @@ func (bs *dbBase) PingMaster() error {
}
// PingSlave pings the slave node to check authentication or keeps the connection alive.
func (bs *dbBase) PingSlave() error {
if slave, err := bs.db.Slave(); err != nil {
func (c *Core) PingSlave() error {
if slave, err := c.DB.Slave(); err != nil {
return err
} else {
return slave.Ping()
@ -264,13 +285,13 @@ func (bs *dbBase) PingSlave() error {
// You should call Commit or Rollback functions of the transaction object
// if you no longer use the transaction. Commit or Rollback functions will also
// close the transaction automatically.
func (bs *dbBase) Begin() (*TX, error) {
if master, err := bs.db.Master(); err != nil {
func (c *Core) Begin() (*TX, error) {
if master, err := c.DB.Master(); err != nil {
return nil, err
} else {
if tx, err := master.Begin(); err == nil {
return &TX{
db: bs.db,
db: c.DB,
tx: tx,
master: master,
}, nil
@ -289,8 +310,8 @@ func (bs *dbBase) Begin() (*TX, error) {
// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"})
//
// The parameter <batch> specifies the batch operation count when given data is slice.
func (bs *dbBase) Insert(table string, data interface{}, batch ...int) (sql.Result, error) {
return bs.db.doInsert(nil, table, data, gINSERT_OPTION_DEFAULT, batch...)
func (c *Core) Insert(table string, data interface{}, batch ...int) (sql.Result, error) {
return c.DB.DoInsert(nil, table, data, gINSERT_OPTION_DEFAULT, batch...)
}
// InsertIgnore does "INSERT IGNORE INTO ..." statement for the table.
@ -302,8 +323,8 @@ func (bs *dbBase) Insert(table string, data interface{}, batch ...int) (sql.Resu
// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"})
//
// The parameter <batch> specifies the batch operation count when given data is slice.
func (bs *dbBase) InsertIgnore(table string, data interface{}, batch ...int) (sql.Result, error) {
return bs.db.doInsert(nil, table, data, gINSERT_OPTION_IGNORE, batch...)
func (c *Core) InsertIgnore(table string, data interface{}, batch ...int) (sql.Result, error) {
return c.DB.DoInsert(nil, table, data, gINSERT_OPTION_IGNORE, batch...)
}
// Replace does "REPLACE INTO ..." statement for the table.
@ -318,8 +339,8 @@ func (bs *dbBase) InsertIgnore(table string, data interface{}, batch ...int) (sq
// The parameter <data> can be type of map/gmap/struct/*struct/[]map/[]struct, etc.
// If given data is type of slice, it then does batch replacing, and the optional parameter
// <batch> specifies the batch operation count.
func (bs *dbBase) Replace(table string, data interface{}, batch ...int) (sql.Result, error) {
return bs.db.doInsert(nil, table, data, gINSERT_OPTION_REPLACE, batch...)
func (c *Core) Replace(table string, data interface{}, batch ...int) (sql.Result, error) {
return c.DB.DoInsert(nil, table, data, gINSERT_OPTION_REPLACE, batch...)
}
// Save does "INSERT INTO ... ON DUPLICATE KEY UPDATE..." statement for the table.
@ -333,54 +354,60 @@ func (bs *dbBase) Replace(table string, data interface{}, batch ...int) (sql.Res
//
// If given data is type of slice, it then does batch saving, and the optional parameter
// <batch> specifies the batch operation count.
func (bs *dbBase) Save(table string, data interface{}, batch ...int) (sql.Result, error) {
return bs.db.doInsert(nil, table, data, gINSERT_OPTION_SAVE, batch...)
func (c *Core) Save(table string, data interface{}, batch ...int) (sql.Result, error) {
return c.DB.DoInsert(nil, table, data, gINSERT_OPTION_SAVE, batch...)
}
// doInsert inserts or updates data for given table.
//
// The parameter <data> can be type of map/gmap/struct/*struct/[]map/[]struct, etc.
// Eg:
// Data(g.Map{"uid": 10000, "name":"john"})
// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"})
//
// The parameter <option> values are as follows:
// 0: insert: just insert, if there's unique/primary key in the data, it returns error;
// 1: replace: if there's unique/primary key in the data, it deletes it from table and inserts a new one;
// 2: save: if there's unique/primary key in the data, it updates it or else inserts a new one;
// 3: ignore: if there's unique/primary key in the data, it ignores the inserting;
func (bs *dbBase) doInsert(link dbLink, table string, data interface{}, option int, batch ...int) (result sql.Result, err error) {
func (c *Core) DoInsert(link Link, table string, data interface{}, option int, batch ...int) (result sql.Result, err error) {
var fields []string
var values []string
var params []interface{}
var dataMap Map
table = bs.db.handleTableName(table)
rv := reflect.ValueOf(data)
kind := rv.Kind()
if kind == reflect.Ptr {
rv = rv.Elem()
kind = rv.Kind()
table = c.DB.QuotePrefixTableName(table)
reflectValue := reflect.ValueOf(data)
reflectKind := reflectValue.Kind()
if reflectKind == reflect.Ptr {
reflectValue = reflectValue.Elem()
reflectKind = reflectValue.Kind()
}
switch kind {
switch reflectKind {
case reflect.Slice, reflect.Array:
return bs.db.doBatchInsert(link, table, data, option, batch...)
return c.DB.DoBatchInsert(link, table, data, option, batch...)
case reflect.Map, reflect.Struct:
dataMap = varToMapDeep(data)
dataMap = DataToMapDeep(data)
default:
return result, errors.New(fmt.Sprint("unsupported data type:", kind))
return result, errors.New(fmt.Sprint("unsupported data type:", reflectKind))
}
if len(dataMap) == 0 {
return nil, errors.New("data cannot be empty")
}
charL, charR := bs.db.getChars()
charL, charR := c.DB.GetChars()
for k, v := range dataMap {
fields = append(fields, charL+k+charR)
values = append(values, "?")
params = append(params, v)
}
operation := getInsertOperationByOption(option)
operation := GetInsertOperationByOption(option)
updateStr := ""
if option == gINSERT_OPTION_SAVE {
for k, _ := range dataMap {
if len(updateStr) > 0 {
updateStr += ","
}
updateStr += fmt.Sprintf("%s%s%s=VALUES(%s%s%s)",
updateStr += fmt.Sprintf(
"%s%s%s=VALUES(%s%s%s)",
charL, k, charR,
charL, k, charR,
)
@ -388,45 +415,50 @@ func (bs *dbBase) doInsert(link dbLink, table string, data interface{}, option i
updateStr = fmt.Sprintf("ON DUPLICATE KEY UPDATE %s", updateStr)
}
if link == nil {
if link, err = bs.db.Master(); err != nil {
if link, err = c.DB.Master(); err != nil {
return nil, err
}
}
return bs.db.doExec(link, fmt.Sprintf("%s INTO %s(%s) VALUES(%s) %s",
operation, table, strings.Join(fields, ","),
strings.Join(values, ","), updateStr),
params...)
return c.DB.DoExec(
link,
fmt.Sprintf(
"%s INTO %s(%s) VALUES(%s) %s",
operation, table, strings.Join(fields, ","),
strings.Join(values, ","), updateStr,
),
params...,
)
}
// BatchInsert batch inserts data.
// The parameter <list> must be type of slice of map or struct.
func (bs *dbBase) BatchInsert(table string, list interface{}, batch ...int) (sql.Result, error) {
return bs.db.doBatchInsert(nil, table, list, gINSERT_OPTION_DEFAULT, batch...)
func (c *Core) BatchInsert(table string, list interface{}, batch ...int) (sql.Result, error) {
return c.DB.DoBatchInsert(nil, table, list, gINSERT_OPTION_DEFAULT, batch...)
}
// BatchInsert batch inserts data with ignore option.
// The parameter <list> must be type of slice of map or struct.
func (bs *dbBase) BatchInsertIgnore(table string, list interface{}, batch ...int) (sql.Result, error) {
return bs.db.doBatchInsert(nil, table, list, gINSERT_OPTION_IGNORE, batch...)
func (c *Core) BatchInsertIgnore(table string, list interface{}, batch ...int) (sql.Result, error) {
return c.DB.DoBatchInsert(nil, table, list, gINSERT_OPTION_IGNORE, batch...)
}
// BatchReplace batch replaces data.
// The parameter <list> must be type of slice of map or struct.
func (bs *dbBase) BatchReplace(table string, list interface{}, batch ...int) (sql.Result, error) {
return bs.db.doBatchInsert(nil, table, list, gINSERT_OPTION_REPLACE, batch...)
func (c *Core) BatchReplace(table string, list interface{}, batch ...int) (sql.Result, error) {
return c.DB.DoBatchInsert(nil, table, list, gINSERT_OPTION_REPLACE, batch...)
}
// BatchSave batch replaces data.
// The parameter <list> must be type of slice of map or struct.
func (bs *dbBase) BatchSave(table string, list interface{}, batch ...int) (sql.Result, error) {
return bs.db.doBatchInsert(nil, table, list, gINSERT_OPTION_SAVE, batch...)
func (c *Core) BatchSave(table string, list interface{}, batch ...int) (sql.Result, error) {
return c.DB.DoBatchInsert(nil, table, list, gINSERT_OPTION_SAVE, batch...)
}
// doBatchInsert batch inserts/replaces/saves data.
func (bs *dbBase) doBatchInsert(link dbLink, table string, list interface{}, option int, batch ...int) (result sql.Result, err error) {
func (c *Core) DoBatchInsert(link Link, table string, list interface{}, option int, batch ...int) (result sql.Result, err error) {
var keys, values []string
var params []interface{}
table = bs.db.handleTableName(table)
table = c.DB.QuotePrefixTableName(table)
listMap := (List)(nil)
switch v := list.(type) {
case Result:
@ -449,10 +481,10 @@ func (bs *dbBase) doBatchInsert(link dbLink, table string, list interface{}, opt
case reflect.Slice, reflect.Array:
listMap = make(List, rv.Len())
for i := 0; i < rv.Len(); i++ {
listMap[i] = varToMapDeep(rv.Index(i).Interface())
listMap[i] = DataToMapDeep(rv.Index(i).Interface())
}
case reflect.Map, reflect.Struct:
listMap = List{varToMapDeep(list)}
listMap = List{DataToMapDeep(list)}
default:
return result, errors.New(fmt.Sprint("unsupported list type:", kind))
}
@ -461,7 +493,7 @@ func (bs *dbBase) doBatchInsert(link dbLink, table string, list interface{}, opt
return result, errors.New("data list cannot be empty")
}
if link == nil {
if link, err = bs.db.Master(); err != nil {
if link, err = c.DB.Master(); err != nil {
return
}
}
@ -471,20 +503,21 @@ func (bs *dbBase) doBatchInsert(link dbLink, table string, list interface{}, opt
keys = append(keys, k)
holders = append(holders, "?")
}
// Prepare the result pointer.
batchResult := new(batchSqlResult)
charL, charR := bs.db.getChars()
// Prepare the batch result pointer.
batchResult := new(SqlResult)
charL, charR := c.DB.GetChars()
keysStr := charL + strings.Join(keys, charR+","+charL) + charR
valueHolderStr := "(" + strings.Join(holders, ",") + ")"
operation := getInsertOperationByOption(option)
operation := GetInsertOperationByOption(option)
updateStr := ""
if option == gINSERT_OPTION_SAVE {
for _, k := range keys {
if len(updateStr) > 0 {
updateStr += ","
}
updateStr += fmt.Sprintf("%s%s%s=VALUES(%s%s%s)",
updateStr += fmt.Sprintf(
"%s%s%s=VALUES(%s%s%s)",
charL, k, charR,
charL, k, charR,
)
@ -504,7 +537,7 @@ func (bs *dbBase) doBatchInsert(link dbLink, table string, list interface{}, opt
}
values = append(values, valueHolderStr)
if len(values) == batchNum || (i == listMapLen-1 && len(values) > 0) {
r, err := bs.db.doExec(
r, err := c.DB.DoExec(
link,
fmt.Sprintf(
"%s INTO %s(%s) VALUES%s %s",
@ -522,8 +555,8 @@ func (bs *dbBase) doBatchInsert(link dbLink, table string, list interface{}, opt
if n, err := r.RowsAffected(); err != nil {
return r, err
} else {
batchResult.lastResult = r
batchResult.rowsAffected += n
batchResult.result = r
batchResult.affected += n
}
params = params[:0]
values = values[:0]
@ -546,18 +579,18 @@ func (bs *dbBase) doBatchInsert(link dbLink, table string, list interface{}, opt
// "status IN (?)", g.Slice{1,2,3}
// "age IN(?,?)", 18, 50
// User{ Id : 1, UserName : "john"}
func (bs *dbBase) Update(table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error) {
newWhere, newArgs := formatWhere(bs.db, condition, args, false)
func (c *Core) Update(table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error) {
newWhere, newArgs := formatWhere(c.DB, condition, args, false)
if newWhere != "" {
newWhere = " WHERE " + newWhere
}
return bs.db.doUpdate(nil, table, data, newWhere, newArgs...)
return c.DB.DoUpdate(nil, table, data, newWhere, newArgs...)
}
// doUpdate does "UPDATE ... " statement for the table.
// Also see Update.
func (bs *dbBase) doUpdate(link dbLink, table string, data interface{}, condition string, args ...interface{}) (result sql.Result, err error) {
table = bs.db.handleTableName(table)
func (c *Core) DoUpdate(link Link, table string, data interface{}, condition string, args ...interface{}) (result sql.Result, err error) {
table = c.DB.QuotePrefixTableName(table)
updates := ""
rv := reflect.ValueOf(data)
kind := rv.Kind()
@ -569,8 +602,8 @@ func (bs *dbBase) doUpdate(link dbLink, table string, data interface{}, conditio
switch kind {
case reflect.Map, reflect.Struct:
var fields []string
for k, v := range varToMapDeep(data) {
fields = append(fields, bs.db.quoteWord(k)+"=?")
for k, v := range DataToMapDeep(data) {
fields = append(fields, c.DB.QuoteWord(k)+"=?")
params = append(params, v)
}
updates = strings.Join(fields, ",")
@ -585,11 +618,15 @@ func (bs *dbBase) doUpdate(link dbLink, table string, data interface{}, conditio
}
// If no link passed, it then uses the master link.
if link == nil {
if link, err = bs.db.Master(); err != nil {
if link, err = c.DB.Master(); err != nil {
return nil, err
}
}
return bs.db.doExec(link, fmt.Sprintf("UPDATE %s SET %s%s", table, updates, condition), args...)
return c.DB.DoExec(
link,
fmt.Sprintf("UPDATE %s SET %s%s", table, updates, condition),
args...,
)
}
// Delete does "DELETE FROM ... " statement for the table.
@ -603,38 +640,28 @@ func (bs *dbBase) doUpdate(link dbLink, table string, data interface{}, conditio
// "status IN (?)", g.Slice{1,2,3}
// "age IN(?,?)", 18, 50
// User{ Id : 1, UserName : "john"}
func (bs *dbBase) Delete(table string, condition interface{}, args ...interface{}) (result sql.Result, err error) {
newWhere, newArgs := formatWhere(bs.db, condition, args, false)
func (c *Core) Delete(table string, condition interface{}, args ...interface{}) (result sql.Result, err error) {
newWhere, newArgs := formatWhere(c.DB, condition, args, false)
if newWhere != "" {
newWhere = " WHERE " + newWhere
}
return bs.db.doDelete(nil, table, newWhere, newArgs...)
return c.DB.DoDelete(nil, table, newWhere, newArgs...)
}
// doDelete does "DELETE FROM ... " statement for the table.
// Also see Delete.
func (bs *dbBase) doDelete(link dbLink, table string, condition string, args ...interface{}) (result sql.Result, err error) {
func (c *Core) DoDelete(link Link, table string, condition string, args ...interface{}) (result sql.Result, err error) {
if link == nil {
if link, err = bs.db.Master(); err != nil {
if link, err = c.DB.Master(); err != nil {
return nil, err
}
}
table = bs.db.handleTableName(table)
return bs.db.doExec(link, fmt.Sprintf("DELETE FROM %s%s", table, condition), args...)
}
// getCache returns the internal cache object.
func (bs *dbBase) getCache() *gcache.Cache {
return bs.cache
}
// getPrefix returns the table prefix string configured.
func (bs *dbBase) getPrefix() string {
return bs.prefix
table = c.DB.QuotePrefixTableName(table)
return c.DB.DoExec(link, fmt.Sprintf("DELETE FROM %s%s", table, condition), args...)
}
// rowsToResult converts underlying data record type sql.Rows to Result type.
func (bs *dbBase) rowsToResult(rows *sql.Rows) (Result, error) {
func (c *Core) rowsToResult(rows *sql.Rows) (Result, error) {
if !rows.Next() {
return nil, nil
}
@ -671,7 +698,7 @@ func (bs *dbBase) rowsToResult(rows *sql.Rows) (Result, error) {
// it should do a copy of it.
v := make([]byte, len(value))
copy(v, value)
row[columnNames[i]] = gvar.New(bs.db.convertValue(v, columnTypes[i]))
row[columnNames[i]] = gvar.New(c.DB.convertValue(v, columnTypes[i]))
}
}
records = append(records, row)
@ -682,39 +709,23 @@ func (bs *dbBase) rowsToResult(rows *sql.Rows) (Result, error) {
return records, nil
}
// handleTableName adds prefix string and quote chars for the table. It handles table string like:
// "user", "user u", "user,user_detail", "user u, user_detail ut", "user as u, user_detail as ut".
// MarshalJSON implements the interface MarshalJSON for json.Marshal.
// It just returns the pointer address.
//
// Note that, this will automatically checks the table prefix whether already added, if true it does
// nothing to the table name, or else adds the prefix to the table name.
func (bs *dbBase) handleTableName(table string) string {
charLeft, charRight := bs.db.getChars()
prefix := bs.db.getPrefix()
return doHandleTableName(table, prefix, charLeft, charRight)
// Note that this interface implements mainly for workaround for a json infinite loop bug
// of Golang version < v1.14.
func (c *Core) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf(`%+v`, c)), nil
}
// quoteWord checks given string <s> a word, if true quotes it with security chars of the database
// and returns the quoted string; or else return <s> without any change.
func (bs *dbBase) quoteWord(s string) string {
charLeft, charRight := bs.db.getChars()
return doQuoteWord(s, charLeft, charRight)
}
// quoteString quotes string with quote chars. Strings like:
// "user", "user u", "user,user_detail", "user u, user_detail ut", "u.id asc".
func (bs *dbBase) quoteString(s string) string {
charLeft, charRight := bs.db.getChars()
return doQuoteString(s, charLeft, charRight)
}
// printSql outputs the sql object to logger.
// writeSqlToLogger outputs the sql object to logger.
// It is enabled when configuration "debug" is true.
func (bs *dbBase) printSql(v *Sql) {
s := fmt.Sprintf("[%d ms] %s", v.End-v.Start, v.Format)
func (c *Core) writeSqlToLogger(v *Sql) {
s := fmt.Sprintf("[%3d ms] %s", v.End-v.Start, v.Format)
if v.Error != nil {
s += "\nError: " + v.Error.Error()
bs.logger.StackWithFilter(gPATH_FILTER_KEY).Error(s)
c.logger.StackWithFilter(gPATH_FILTER_KEY).Error(s)
} else {
bs.logger.StackWithFilter(gPATH_FILTER_KEY).Debug(s)
c.logger.StackWithFilter(gPATH_FILTER_KEY).Debug(s)
}
}

View File

@ -8,6 +8,7 @@ package gdb
import (
"fmt"
"github.com/gogf/gf/os/gcache"
"sync"
"time"
@ -114,29 +115,29 @@ func GetDefaultGroup() string {
}
// SetLogger sets the logger for orm.
func (bs *dbBase) SetLogger(logger *glog.Logger) {
bs.logger = logger
func (c *Core) SetLogger(logger *glog.Logger) {
c.logger = logger
}
// GetLogger returns the logger of the orm.
func (bs *dbBase) GetLogger() *glog.Logger {
return bs.logger
func (c *Core) GetLogger() *glog.Logger {
return c.logger
}
// SetMaxIdleConnCount sets the max idle connection count for underlying connection pool.
func (bs *dbBase) SetMaxIdleConnCount(n int) {
bs.maxIdleConnCount = n
func (c *Core) SetMaxIdleConnCount(n int) {
c.maxIdleConnCount = n
}
// SetMaxOpenConnCount sets the max open connection count for underlying connection pool.
func (bs *dbBase) SetMaxOpenConnCount(n int) {
bs.maxOpenConnCount = n
func (c *Core) SetMaxOpenConnCount(n int) {
c.maxOpenConnCount = n
}
// SetMaxConnLifetime sets the connection TTL for underlying connection pool.
// If parameter <d> <= 0, it means the connection never expires.
func (bs *dbBase) SetMaxConnLifetime(d time.Duration) {
bs.maxConnLifetime = d
func (c *Core) SetMaxConnLifetime(d time.Duration) {
c.maxConnLifetime = d
}
// String returns the node as string.
@ -155,14 +156,36 @@ func (node *ConfigNode) String() string {
}
// SetDebug enables/disables the debug mode.
func (bs *dbBase) SetDebug(debug bool) {
if bs.debug.Val() == debug {
func (c *Core) SetDebug(debug bool) {
if c.debug.Val() == debug {
return
}
bs.debug.Set(debug)
c.debug.Set(debug)
}
// getDebug returns the debug value.
func (bs *dbBase) getDebug() bool {
return bs.debug.Val()
// GetDebug returns the debug value.
func (c *Core) GetDebug() bool {
return c.debug.Val()
}
// GetCache returns the internal cache object.
func (c *Core) GetCache() *gcache.Cache {
return c.cache
}
// GetPrefix returns the table prefix string configured.
func (c *Core) GetPrefix() string {
return c.prefix
}
// SetSchema changes the schema for this database connection object.
// Importantly note that when schema configuration changed for the database,
// it affects all operations on the database object in the future.
func (c *Core) SetSchema(schema string) {
c.schema.Set(schema)
}
// GetSchema returns the schema configured.
func (c *Core) GetSchema() string {
return c.schema.Val()
}

View File

@ -0,0 +1,86 @@
// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
//
package gdb
import (
"database/sql"
)
// GetMaster acts like function Master but with additional <schema> parameter specifying
// the schema for the connection. It is defined for internal usage.
// Also see Master.
func (c *Core) GetMaster(schema ...string) (*sql.DB, error) {
return c.getSqlDb(true, schema...)
}
// GetSlave acts like function Slave but with additional <schema> parameter specifying
// the schema for the connection. It is defined for internal usage.
// Also see Slave.
func (c *Core) GetSlave(schema ...string) (*sql.DB, error) {
return c.getSqlDb(false, schema...)
}
// QuoteWord checks given string <s> a word, if true quotes it with security chars of the database
// and returns the quoted string; or else return <s> without any change.
func (c *Core) QuoteWord(s string) string {
charLeft, charRight := c.DB.GetChars()
return doQuoteWord(s, charLeft, charRight)
}
// QuoteString quotes string with quote chars. Strings like:
// "user", "user u", "user,user_detail", "user u, user_detail ut", "u.id asc".
func (c *Core) QuoteString(s string) string {
charLeft, charRight := c.DB.GetChars()
return doQuoteString(s, charLeft, charRight)
}
// QuotePrefixTableName adds prefix string and quotes chars for the table.
// It handles table string like:
// "user", "user u",
// "user,user_detail",
// "user u, user_detail ut",
// "user as u, user_detail as ut".
//
// Note that, this will automatically checks the table prefix whether already added,
// if true it does nothing to the table name, or else adds the prefix to the table name.
func (c *Core) QuotePrefixTableName(table string) string {
charLeft, charRight := c.DB.GetChars()
return doHandleTableName(table, c.DB.GetPrefix(), charLeft, charRight)
}
// GetChars returns the security char for current database.
// It does nothing in default.
func (c *Core) GetChars() (charLeft string, charRight string) {
return "", ""
}
// HandleSqlBeforeCommit handles the sql before posts it to database.
// It does nothing in default.
func (c *Core) HandleSqlBeforeCommit(sql string) string {
return sql
}
// Tables retrieves and returns the tables of current schema.
// It's mainly used in cli tool chain for automatically generating the models.
//
// It does nothing in default.
func (c *Core) Tables(schema ...string) (tables []string, err error) {
return
}
// TableFields retrieves and returns the fields information of specified table of current schema.
//
// Note that it returns a map containing the field name and its corresponding fields.
// As a map is unsorted, the TableField struct has a "Index" field marks its sequence in the fields.
//
// It's using cache feature to enhance the performance, which is never expired util the process restarts.
//
// It does nothing in default.
func (c *Core) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) {
return
}

View File

@ -5,7 +5,7 @@
// You can obtain one at https://github.com/gogf/gf.
//
// Note:
// 1. It needs manually import: _ "github.com/lib/pq"
// 1. It needs manually import: _ "github.com/denisenkom/go-mssqldb"
// 2. It does not support Save/Replace features.
// 3. It does not support LastInsertId.
@ -22,11 +22,21 @@ import (
"github.com/gogf/gf/text/gregex"
)
type dbMssql struct {
*dbBase
// DriverMssql is the driver for SQL server database.
type DriverMssql struct {
*Core
}
func (db *dbMssql) Open(config *ConfigNode) (*sql.DB, error) {
// New creates and returns a database object for SQL server.
// It implements the interface of gdb.Driver for extra database driver installation.
func (d *DriverMssql) New(core *Core, node *ConfigNode) (DB, error) {
return &DriverMssql{
Core: core,
}, nil
}
// Open creates and returns a underlying sql.DB object for mssql.
func (d *DriverMssql) Open(config *ConfigNode) (*sql.DB, error) {
source := ""
if config.LinkInfo != "" {
source = config.LinkInfo
@ -44,21 +54,26 @@ func (db *dbMssql) Open(config *ConfigNode) (*sql.DB, error) {
}
}
func (db *dbMssql) getChars() (charLeft string, charRight string) {
// GetChars returns the security char for this type of database.
func (d *DriverMssql) GetChars() (charLeft string, charRight string) {
return "\"", "\""
}
func (db *dbMssql) handleSqlBeforeExec(query string) string {
index := 0
str, _ := gregex.ReplaceStringFunc("\\?", query, func(s string) string {
// HandleSqlBeforeCommit deals with the sql string before commits it to underlying sql driver.
func (d *DriverMssql) HandleSqlBeforeCommit(link Link, sql string, args []interface{}) (string, []interface{}) {
var index int
// Convert place holder char '?' to string "@px".
str, _ := gregex.ReplaceStringFunc("\\?", sql, func(s string) string {
index++
return fmt.Sprintf("@p%d", index)
})
str, _ = gregex.ReplaceString("\"", "", str)
return db.parseSql(str)
return d.parseSql(str), args
}
func (db *dbMssql) parseSql(sql string) string {
// parseSql does some replacement of the sql before commits it to underlying driver,
// for support of microsoft sql server.
func (d *DriverMssql) parseSql(sql string) string {
// SELECT * FROM USER WHERE ID=1 LIMIT 1
if m, _ := gregex.MatchString(`^SELECT(.+)LIMIT 1$`, sql); len(m) > 1 {
return fmt.Sprintf(`SELECT TOP 1 %s`, m[1])
@ -78,72 +93,70 @@ func (db *dbMssql) parseSql(sql string) string {
index++
switch keyword {
case "SELECT":
// 不含LIMIT关键字则不处理
// LIMIT statement checks.
if len(res) < 2 ||
(strings.HasPrefix(res[index][0], "LIMIT") == false &&
strings.HasPrefix(res[index][0], "limit") == false) {
break
}
// 不含LIMIT则不处理
if gregex.IsMatchString("((?i)SELECT)(.+)((?i)LIMIT)", sql) == false {
break
}
// 判断SQL中是否含有order by
// ORDER BY statement checks.
selectStr := ""
orderStr := ""
haveOrder := gregex.IsMatchString("((?i)SELECT)(.+)((?i)ORDER BY)", sql)
if haveOrder {
// 取order by 前面的字符串
queryExpr, _ := gregex.MatchString("((?i)SELECT)(.+)((?i)ORDER BY)", sql)
if len(queryExpr) != 4 || strings.EqualFold(queryExpr[1], "SELECT") == false || strings.EqualFold(queryExpr[3], "ORDER BY") == false {
if len(queryExpr) != 4 ||
strings.EqualFold(queryExpr[1], "SELECT") == false ||
strings.EqualFold(queryExpr[3], "ORDER BY") == false {
break
}
selectStr = queryExpr[2]
// 取order by表达式的值
orderExpr, _ := gregex.MatchString("((?i)ORDER BY)(.+)((?i)LIMIT)", sql)
if len(orderExpr) != 4 || strings.EqualFold(orderExpr[1], "ORDER BY") == false || strings.EqualFold(orderExpr[3], "LIMIT") == false {
if len(orderExpr) != 4 ||
strings.EqualFold(orderExpr[1], "ORDER BY") == false ||
strings.EqualFold(orderExpr[3], "LIMIT") == false {
break
}
orderStr = orderExpr[2]
} else {
queryExpr, _ := gregex.MatchString("((?i)SELECT)(.+)((?i)LIMIT)", sql)
if len(queryExpr) != 4 || strings.EqualFold(queryExpr[1], "SELECT") == false || strings.EqualFold(queryExpr[3], "LIMIT") == false {
if len(queryExpr) != 4 ||
strings.EqualFold(queryExpr[1], "SELECT") == false ||
strings.EqualFold(queryExpr[3], "LIMIT") == false {
break
}
selectStr = queryExpr[2]
}
// 取limit后面的取值范围
first, limit := 0, 0
for i := 1; i < len(res[index]); i++ {
if len(strings.TrimSpace(res[index][i])) == 0 {
continue
}
if strings.HasPrefix(res[index][i], "LIMIT") || strings.HasPrefix(res[index][i], "limit") {
if strings.HasPrefix(res[index][i], "LIMIT") ||
strings.HasPrefix(res[index][i], "limit") {
first, _ = strconv.Atoi(res[index][i+1])
limit, _ = strconv.Atoi(res[index][i+2])
break
}
}
if haveOrder {
sql = fmt.Sprintf(
"SELECT * FROM "+
"(SELECT ROW_NUMBER() OVER (ORDER BY %s) as ROWNUMBER_, %s ) as TMP_ "+
"WHERE TMP_.ROWNUMBER_ > %d AND TMP_.ROWNUMBER_ <= %d",
orderStr, selectStr, first, limit,
orderStr, selectStr, first, first+limit,
)
} else {
if first == 0 {
first = limit
} else {
first = limit - first
}
sql = fmt.Sprintf(
"SELECT * FROM (SELECT TOP %d * FROM (SELECT TOP %d %s) as TMP1_ ) as TMP2_ ",
first, limit, selectStr,
limit, first+limit, selectStr,
)
}
default:
@ -151,29 +164,46 @@ func (db *dbMssql) parseSql(sql string) string {
return sql
}
// TODO
func (db *dbMssql) Tables(schema ...string) (tables []string, err error) {
// Tables retrieves and returns the tables of current schema.
// It's mainly used in cli tool chain for automatically generating the models.
func (d *DriverMssql) Tables(schema ...string) (tables []string, err error) {
var result Result
link, err := d.DB.GetSlave(schema...)
if err != nil {
return nil, err
}
result, err = d.DB.DoGetAll(link, `SELECT NAME FROM SYSOBJECTS WHERE XTYPE='U' AND STATUS >= 0 ORDER BY NAME`)
if err != nil {
return
}
for _, m := range result {
for _, v := range m {
tables = append(tables, v.String())
}
}
return
}
func (db *dbMssql) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) {
// TableFields retrieves and returns the fields information of specified table of current schema.
func (d *DriverMssql) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) {
table = gstr.Trim(table)
if gstr.Contains(table, " ") {
panic("function TableFields supports only single table operations")
}
checkSchema := db.schema.Val()
checkSchema := d.DB.GetSchema()
if len(schema) > 0 && schema[0] != "" {
checkSchema = schema[0]
}
v := db.cache.GetOrSetFunc(
v := d.DB.GetCache().GetOrSetFunc(
fmt.Sprintf(`mssql_table_fields_%s_%s`, table, checkSchema), func() interface{} {
var result Result
var link *sql.DB
link, err = db.getSlave(checkSchema)
link, err = d.DB.GetSlave(checkSchema)
if err != nil {
return nil
}
result, err = db.doGetAll(link, fmt.Sprintf(`
result, err = d.DB.DoGetAll(link, fmt.Sprintf(`
SELECT c.name as FIELD, CASE t.name
WHEN 'numeric' THEN t.name + '(' + convert(varchar(20),c.xprec) + ',' + convert(varchar(20),c.xscale) + ')'
WHEN 'char' THEN t.name + '(' + convert(varchar(20),c.length)+ ')'

View File

@ -0,0 +1,130 @@
// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gdb
import (
"database/sql"
"fmt"
"github.com/gogf/gf/internal/intlog"
"github.com/gogf/gf/text/gstr"
_ "github.com/go-sql-driver/mysql"
)
// DriverMysql is the driver for mysql database.
type DriverMysql struct {
*Core
}
// New creates and returns a database object for mysql.
// It implements the interface of gdb.Driver for extra database driver installation.
func (d *DriverMysql) New(core *Core, node *ConfigNode) (DB, error) {
return &DriverMysql{
Core: core,
}, nil
}
// Open creates and returns a underlying sql.DB object for mysql.
func (d *DriverMysql) Open(config *ConfigNode) (*sql.DB, error) {
var source string
if config.LinkInfo != "" {
source = config.LinkInfo
} else {
source = fmt.Sprintf(
"%s:%s@tcp(%s:%s)/%s?charset=%s&multiStatements=true&parseTime=true&loc=Local",
config.User, config.Pass, config.Host, config.Port, config.Name, config.Charset,
)
}
intlog.Printf("Open: %s", source)
if db, err := sql.Open("mysql", source); err == nil {
return db, nil
} else {
return nil, err
}
}
// GetChars returns the security char for this type of database.
func (d *DriverMysql) GetChars() (charLeft string, charRight string) {
return "`", "`"
}
// HandleSqlBeforeCommit handles the sql before posts it to database.
func (d *DriverMysql) HandleSqlBeforeCommit(link Link, sql string, args []interface{}) (string, []interface{}) {
return sql, args
}
// Tables retrieves and returns the tables of current schema.
// It's mainly used in cli tool chain for automatically generating the models.
func (d *DriverMysql) Tables(schema ...string) (tables []string, err error) {
var result Result
link, err := d.DB.GetSlave(schema...)
if err != nil {
return nil, err
}
result, err = d.DB.DoGetAll(link, `SHOW TABLES`)
if err != nil {
return
}
for _, m := range result {
for _, v := range m {
tables = append(tables, v.String())
}
}
return
}
// TableFields retrieves and returns the fields information of specified table of current schema.
//
// Note that it returns a map containing the field name and its corresponding fields.
// As a map is unsorted, the TableField struct has a "Index" field marks its sequence in the fields.
//
// It's using cache feature to enhance the performance, which is never expired util the process restarts.
func (d *DriverMysql) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) {
table = gstr.Trim(table)
if gstr.Contains(table, " ") {
panic("function TableFields supports only single table operations")
}
checkSchema := d.schema.Val()
if len(schema) > 0 && schema[0] != "" {
checkSchema = schema[0]
}
v := d.cache.GetOrSetFunc(
fmt.Sprintf(`mysql_table_fields_%s_%s`, table, checkSchema),
func() interface{} {
var result Result
var link *sql.DB
link, err = d.DB.GetSlave(checkSchema)
if err != nil {
return nil
}
result, err = d.DB.DoGetAll(
link,
fmt.Sprintf(`SHOW FULL COLUMNS FROM %s`, d.DB.QuoteWord(table)),
)
if err != nil {
return nil
}
fields = make(map[string]*TableField)
for i, m := range result {
fields[m["Field"].String()] = &TableField{
Index: i,
Name: m["Field"].String(),
Type: m["Type"].String(),
Null: m["Null"].Bool(),
Key: m["Key"].String(),
Default: m["Default"].Val(),
Extra: m["Extra"].String(),
Comment: m["Comment"].String(),
}
}
return fields
}, 0)
if err == nil {
fields = v.(map[string]*TableField)
}
return
}

View File

@ -24,8 +24,9 @@ import (
"github.com/gogf/gf/text/gregex"
)
type dbOracle struct {
*dbBase
// DriverOracle is the driver for oracle database.
type DriverOracle struct {
*Core
}
const (
@ -33,7 +34,16 @@ const (
tableAlias2 = "GFORM2"
)
func (db *dbOracle) Open(config *ConfigNode) (*sql.DB, error) {
// New creates and returns a database object for oracle.
// It implements the interface of gdb.Driver for extra database driver installation.
func (d *DriverOracle) New(core *Core, node *ConfigNode) (DB, error) {
return &DriverOracle{
Core: core,
}, nil
}
// Open creates and returns a underlying sql.DB object for oracle.
func (d *DriverOracle) Open(config *ConfigNode) (*sql.DB, error) {
var source string
if config.LinkInfo != "" {
source = config.LinkInfo
@ -48,21 +58,26 @@ func (db *dbOracle) Open(config *ConfigNode) (*sql.DB, error) {
}
}
func (db *dbOracle) getChars() (charLeft string, charRight string) {
// GetChars returns the security char for this type of database.
func (d *DriverOracle) GetChars() (charLeft string, charRight string) {
return "\"", "\""
}
func (db *dbOracle) handleSqlBeforeExec(query string) string {
index := 0
str, _ := gregex.ReplaceStringFunc("\\?", query, func(s string) string {
// HandleSqlBeforeCommit deals with the sql string before commits it to underlying sql driver.
func (d *DriverOracle) HandleSqlBeforeCommit(link Link, sql string, args []interface{}) (string, []interface{}) {
var index int
// Convert place holder char '?' to string ":x".
str, _ := gregex.ReplaceStringFunc("\\?", sql, func(s string) string {
index++
return fmt.Sprintf(":%d", index)
})
str, _ = gregex.ReplaceString("\"", "", str)
return db.parseSql(str)
return d.parseSql(str), args
}
func (db *dbOracle) parseSql(sql string) string {
// parseSql does some replacement of the sql before commits it to underlying driver,
// for support of oracle server.
func (d *DriverOracle) parseSql(sql string) string {
patten := `^\s*(?i)(SELECT)|(LIMIT\s*(\d+)\s*,\s*(\d+))`
if gregex.IsMatchString(patten, sql) == false {
return sql
@ -80,22 +95,18 @@ func (db *dbOracle) parseSql(sql string) string {
index++
switch keyword {
case "SELECT":
// 不含LIMIT关键字则不处理
if len(res) < 2 || (strings.HasPrefix(res[index][0], "LIMIT") == false && strings.HasPrefix(res[index][0], "limit") == false) {
if len(res) < 2 || (strings.HasPrefix(res[index][0], "LIMIT") == false &&
strings.HasPrefix(res[index][0], "limit") == false) {
break
}
// 取limit前面的字符串
if gregex.IsMatchString("((?i)SELECT)(.+)((?i)LIMIT)", sql) == false {
break
}
queryExpr, _ := gregex.MatchString("((?i)SELECT)(.+)((?i)LIMIT)", sql)
if len(queryExpr) != 4 || strings.EqualFold(queryExpr[1], "SELECT") == false || strings.EqualFold(queryExpr[3], "LIMIT") == false {
if len(queryExpr) != 4 || strings.EqualFold(queryExpr[1], "SELECT") == false ||
strings.EqualFold(queryExpr[3], "LIMIT") == false {
break
}
// 取limit后面的取值范围
first, limit := 0, 0
for i := 1; i < len(res[index]); i++ {
if len(strings.TrimSpace(res[index][i])) == 0 {
@ -108,32 +119,48 @@ func (db *dbOracle) parseSql(sql string) string {
break
}
}
//也可以使用between,据说这种写法的性能会比between好点,里层SQL中的ROWNUM_ >= limit可以缩小查询后的数据集规模
sql = fmt.Sprintf("SELECT * FROM (SELECT GFORM.*, ROWNUM ROWNUM_ FROM (%s %s) GFORM WHERE ROWNUM <= %d) WHERE ROWNUM_ >= %d", queryExpr[1], queryExpr[2], limit, first)
sql = fmt.Sprintf(
"SELECT * FROM "+
"(SELECT GFORM.*, ROWNUM ROWNUM_ FROM (%s %s) GFORM WHERE ROWNUM <= %d)"+
" WHERE ROWNUM_ >= %d",
queryExpr[1], queryExpr[2], limit, first,
)
}
return sql
}
// TODO
func (db *dbOracle) Tables(schema ...string) (tables []string, err error) {
// Tables retrieves and returns the tables of current schema.
// It's mainly used in cli tool chain for automatically generating the models.
// Note that it ignores the parameter <schema> in oracle database, as it is not necessary.
func (d *DriverOracle) Tables(schema ...string) (tables []string, err error) {
var result Result
result, err = d.DB.DoGetAll(nil, "SELECT TABLE_NAME FROM USER_TABLES ORDER BY TABLE_NAME")
if err != nil {
return
}
for _, m := range result {
for _, v := range m {
tables = append(tables, v.String())
}
}
return
}
func (db *dbOracle) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) {
// TableFields retrieves and returns the fields information of specified table of current schema.
func (d *DriverOracle) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) {
table = gstr.Trim(table)
if gstr.Contains(table, " ") {
panic("function TableFields supports only single table operations")
}
checkSchema := db.schema.Val()
checkSchema := d.DB.GetSchema()
if len(schema) > 0 && schema[0] != "" {
checkSchema = schema[0]
}
v := db.cache.GetOrSetFunc(
v := d.DB.GetCache().GetOrSetFunc(
fmt.Sprintf(`oracle_table_fields_%s_%s`, table, checkSchema),
func() interface{} {
result := (Result)(nil)
result, err = db.GetAll(fmt.Sprintf(`
result, err = d.DB.GetAll(fmt.Sprintf(`
SELECT COLUMN_NAME AS FIELD, CASE DATA_TYPE
WHEN 'NUMBER' THEN DATA_TYPE||'('||DATA_PRECISION||','||DATA_SCALE||')'
WHEN 'FLOAT' THEN DATA_TYPE||'('||DATA_PRECISION||','||DATA_SCALE||')'
@ -158,11 +185,11 @@ func (db *dbOracle) TableFields(table string, schema ...string) (fields map[stri
return
}
func (db *dbOracle) getTableUniqueIndex(table string) (fields map[string]map[string]string, err error) {
func (d *DriverOracle) getTableUniqueIndex(table string) (fields map[string]map[string]string, err error) {
table = strings.ToUpper(table)
v := db.cache.GetOrSetFunc("table_unique_index_"+table, func() interface{} {
v := d.DB.GetCache().GetOrSetFunc("table_unique_index_"+table, func() interface{} {
res := (Result)(nil)
res, err = db.GetAll(fmt.Sprintf(`
res, err = d.DB.GetAll(fmt.Sprintf(`
SELECT INDEX_NAME,COLUMN_NAME,CHAR_LENGTH FROM USER_IND_COLUMNS
WHERE TABLE_NAME = '%s'
AND INDEX_NAME IN(SELECT INDEX_NAME FROM USER_INDEXES WHERE TABLE_NAME='%s' AND UNIQUENESS='UNIQUE')
@ -184,7 +211,7 @@ func (db *dbOracle) getTableUniqueIndex(table string) (fields map[string]map[str
return
}
func (db *dbOracle) doInsert(link dbLink, table string, data interface{}, option int, batch ...int) (result sql.Result, err error) {
func (d *DriverOracle) DoInsert(link Link, table string, data interface{}, option int, batch ...int) (result sql.Result, err error) {
var fields []string
var values []string
var params []interface{}
@ -199,11 +226,11 @@ func (db *dbOracle) doInsert(link dbLink, table string, data interface{}, option
case reflect.Slice:
fallthrough
case reflect.Array:
return db.db.doBatchInsert(link, table, data, option, batch...)
return d.DB.DoBatchInsert(link, table, data, option, batch...)
case reflect.Map:
fallthrough
case reflect.Struct:
dataMap = varToMapDeep(data)
dataMap = DataToMapDeep(data)
default:
return result, errors.New(fmt.Sprint("unsupported data type:", kind))
}
@ -212,7 +239,7 @@ func (db *dbOracle) doInsert(link dbLink, table string, data interface{}, option
indexMap := make(map[string]string)
indexExists := false
if option != gINSERT_OPTION_DEFAULT {
index, err := db.getTableUniqueIndex(table)
index, err := d.getTableUniqueIndex(table)
if err != nil {
return nil, err
}
@ -234,7 +261,7 @@ func (db *dbOracle) doInsert(link dbLink, table string, data interface{}, option
onStr := make([]string, 0)
updateStr := make([]string, 0)
charL, charR := db.db.getChars()
charL, charR := d.DB.GetChars()
for k, v := range dataMap {
k = strings.ToUpper(k)
@ -260,7 +287,7 @@ func (db *dbOracle) doInsert(link dbLink, table string, data interface{}, option
}
if link == nil {
if link, err = db.db.Master(); err != nil {
if link, err = d.DB.Master(); err != nil {
return nil, err
}
}
@ -275,9 +302,9 @@ func (db *dbOracle) doInsert(link dbLink, table string, data interface{}, option
table, tableAlias1, strings.Join(subSqlStr, ","), tableAlias2,
strings.Join(onStr, "AND"), strings.Join(updateStr, ","), strings.Join(fields, ","), strings.Join(values, ","),
)
return db.db.doExec(link, tmp, params...)
return d.DB.DoExec(link, tmp, params...)
case gINSERT_OPTION_IGNORE:
return db.db.doExec(link,
return d.DB.DoExec(link,
fmt.Sprintf(
"INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(%s(%s)) */ INTO %s(%s) VALUES(%s)",
table, strings.Join(indexs, ","), table, strings.Join(fields, ","), strings.Join(values, ","),
@ -286,7 +313,7 @@ func (db *dbOracle) doInsert(link dbLink, table string, data interface{}, option
}
}
return db.db.doExec(
return d.DB.DoExec(
link,
fmt.Sprintf(
"INSERT INTO %s(%s) VALUES(%s)",
@ -295,7 +322,7 @@ func (db *dbOracle) doInsert(link dbLink, table string, data interface{}, option
params...)
}
func (db *dbOracle) doBatchInsert(link dbLink, table string, list interface{}, option int, batch ...int) (result sql.Result, err error) {
func (d *DriverOracle) DoBatchInsert(link Link, table string, list interface{}, option int, batch ...int) (result sql.Result, err error) {
var keys []string
var values []string
var params []interface{}
@ -323,12 +350,12 @@ func (db *dbOracle) doBatchInsert(link dbLink, table string, list interface{}, o
case reflect.Array:
listMap = make(List, rv.Len())
for i := 0; i < rv.Len(); i++ {
listMap[i] = varToMapDeep(rv.Index(i).Interface())
listMap[i] = DataToMapDeep(rv.Index(i).Interface())
}
case reflect.Map:
fallthrough
case reflect.Struct:
listMap = List{Map(varToMapDeep(list))}
listMap = List{Map(DataToMapDeep(list))}
default:
return result, errors.New(fmt.Sprint("unsupported list type:", kind))
}
@ -338,7 +365,7 @@ func (db *dbOracle) doBatchInsert(link dbLink, table string, list interface{}, o
return result, errors.New("empty data list")
}
if link == nil {
if link, err = db.db.Master(); err != nil {
if link, err = d.DB.Master(); err != nil {
return
}
}
@ -348,15 +375,15 @@ func (db *dbOracle) doBatchInsert(link dbLink, table string, list interface{}, o
keys = append(keys, k)
holders = append(holders, "?")
}
batchResult := new(batchSqlResult)
charL, charR := db.db.getChars()
batchResult := new(SqlResult)
charL, charR := d.DB.GetChars()
keyStr := charL + strings.Join(keys, charL+","+charR) + charR
valueHolderStr := strings.Join(holders, ",")
// 当操作类型非insert时调用单笔的insert功能
if option != gINSERT_OPTION_DEFAULT {
for _, v := range listMap {
r, err := db.doInsert(link, table, v, option, 1)
r, err := d.DB.DoInsert(link, table, v, option, 1)
if err != nil {
return r, err
}
@ -364,8 +391,8 @@ func (db *dbOracle) doBatchInsert(link dbLink, table string, list interface{}, o
if n, err := r.RowsAffected(); err != nil {
return r, err
} else {
batchResult.lastResult = r
batchResult.rowsAffected += n
batchResult.result = r
batchResult.affected += n
}
}
return batchResult, nil
@ -383,18 +410,17 @@ func (db *dbOracle) doBatchInsert(link dbLink, table string, list interface{}, o
params = append(params, listMap[i][k])
}
values = append(values, valueHolderStr)
intoStr = append(intoStr, fmt.Sprintf(" INTO %s(%s) VALUES(%s) ", table, keyStr, valueHolderStr))
if len(intoStr) == batchNum {
r, err := db.db.doExec(link, fmt.Sprintf("INSERT ALL %s SELECT * FROM DUAL", strings.Join(intoStr, " ")), params...)
r, err := d.DB.DoExec(link, fmt.Sprintf("INSERT ALL %s SELECT * FROM DUAL", strings.Join(intoStr, " ")), params...)
if err != nil {
return r, err
}
if n, err := r.RowsAffected(); err != nil {
return r, err
} else {
batchResult.lastResult = r
batchResult.rowsAffected += n
batchResult.result = r
batchResult.affected += n
}
params = params[:0]
intoStr = intoStr[:0]
@ -402,15 +428,15 @@ func (db *dbOracle) doBatchInsert(link dbLink, table string, list interface{}, o
}
// 处理最后不构成指定批量的数据
if len(intoStr) > 0 {
r, err := db.db.doExec(link, fmt.Sprintf("INSERT ALL %s SELECT * FROM DUAL", strings.Join(intoStr, " ")), params...)
r, err := d.DB.DoExec(link, fmt.Sprintf("INSERT ALL %s SELECT * FROM DUAL", strings.Join(intoStr, " ")), params...)
if err != nil {
return r, err
}
if n, err := r.RowsAffected(); err != nil {
return r, err
} else {
batchResult.lastResult = r
batchResult.rowsAffected += n
batchResult.result = r
batchResult.affected += n
}
}
return batchResult, nil

View File

@ -21,11 +21,21 @@ import (
"github.com/gogf/gf/text/gregex"
)
type dbPgsql struct {
*dbBase
// DriverPgsql is the driver for postgresql database.
type DriverPgsql struct {
*Core
}
func (db *dbPgsql) Open(config *ConfigNode) (*sql.DB, error) {
// New creates and returns a database object for postgresql.
// It implements the interface of gdb.Driver for extra database driver installation.
func (d *DriverPgsql) New(core *Core, node *ConfigNode) (DB, error) {
return &DriverPgsql{
Core: core,
}, nil
}
// Open creates and returns a underlying sql.DB object for pgsql.
func (d *DriverPgsql) Open(config *ConfigNode) (*sql.DB, error) {
var source string
if config.LinkInfo != "" {
source = config.LinkInfo
@ -43,44 +53,68 @@ func (db *dbPgsql) Open(config *ConfigNode) (*sql.DB, error) {
}
}
func (db *dbPgsql) getChars() (charLeft string, charRight string) {
// GetChars returns the security char for this type of database.
func (d *DriverPgsql) GetChars() (charLeft string, charRight string) {
return "\"", "\""
}
func (db *dbPgsql) handleSqlBeforeExec(sql string) string {
index := 0
// HandleSqlBeforeCommit deals with the sql string before commits it to underlying sql driver.
func (d *DriverPgsql) HandleSqlBeforeCommit(link Link, sql string, args []interface{}) (string, []interface{}) {
var index int
// Convert place holder char '?' to string "$x".
sql, _ = gregex.ReplaceStringFunc("\\?", sql, func(s string) string {
index++
return fmt.Sprintf("$%d", index)
})
sql, _ = gregex.ReplaceString(` LIMIT (\d+),\s*(\d+)`, ` LIMIT $1 OFFSET $2`, sql)
return sql
sql, _ = gregex.ReplaceString(` LIMIT (\d+),\s*(\d+)`, ` LIMIT $2 OFFSET $1`, sql)
return sql, args
}
// TODO
func (db *dbPgsql) Tables(schema ...string) (tables []string, err error) {
// Tables retrieves and returns the tables of current schema.
// It's mainly used in cli tool chain for automatically generating the models.
func (d *DriverPgsql) Tables(schema ...string) (tables []string, err error) {
var result Result
link, err := d.DB.GetSlave(schema...)
if err != nil {
return nil, err
}
query := "SELECT TABLENAME FROM PG_TABLES WHERE SCHEMANAME = 'public' ORDER BY TABLENAME"
if len(schema) > 0 && schema[0] != "" {
query = fmt.Sprintf("SELECT TABLENAME FROM PG_TABLES WHERE SCHEMANAME = '%s' ORDER BY TABLENAME", schema[0])
}
result, err = d.DB.DoGetAll(link, query)
if err != nil {
return
}
for _, m := range result {
for _, v := range m {
tables = append(tables, v.String())
}
}
return
}
func (db *dbPgsql) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) {
// TableFields retrieves and returns the fields information of specified table of current schema.
func (d *DriverPgsql) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) {
table = gstr.Trim(table)
if gstr.Contains(table, " ") {
panic("function TableFields supports only single table operations")
}
table, _ = gregex.ReplaceString("\"", "", table)
checkSchema := db.schema.Val()
checkSchema := d.DB.GetSchema()
if len(schema) > 0 && schema[0] != "" {
checkSchema = schema[0]
}
v := db.cache.GetOrSetFunc(
v := d.DB.GetCache().GetOrSetFunc(
fmt.Sprintf(`pgsql_table_fields_%s_%s`, table, checkSchema), func() interface{} {
var result Result
var link *sql.DB
link, err = db.getSlave(checkSchema)
link, err = d.DB.GetSlave(checkSchema)
if err != nil {
return nil
}
result, err = db.doGetAll(link, fmt.Sprintf(`
result, err = d.DB.DoGetAll(link, fmt.Sprintf(`
SELECT a.attname AS field, t.typname AS type FROM pg_class c, pg_attribute a
LEFT OUTER JOIN pg_description b ON a.attrelid=b.objoid AND a.attnum = b.objsubid,pg_type t
WHERE c.relname = '%s' and a.attnum > 0 and a.attrelid = c.oid and a.atttypid = t.oid

View File

@ -0,0 +1,126 @@
// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
//
// Note:
// 1. It needs manually import: _ "github.com/mattn/go-sqlite3"
// 2. It does not support Save/Replace features.
package gdb
import (
"database/sql"
"fmt"
"github.com/gogf/gf/internal/intlog"
"github.com/gogf/gf/os/gfile"
"github.com/gogf/gf/text/gstr"
"strings"
)
// DriverSqlite is the driver for sqlite database.
type DriverSqlite struct {
*Core
}
// New creates and returns a database object for sqlite.
// It implements the interface of gdb.Driver for extra database driver installation.
func (d *DriverSqlite) New(core *Core, node *ConfigNode) (DB, error) {
return &DriverSqlite{
Core: core,
}, nil
}
// Open creates and returns a underlying sql.DB object for sqlite.
func (d *DriverSqlite) Open(config *ConfigNode) (*sql.DB, error) {
var source string
var err error
if config.LinkInfo != "" {
source = config.LinkInfo
} else {
source = config.Name
}
source, err = gfile.Search(source)
if err != nil {
return nil, err
}
intlog.Printf("Open: %s", source)
if db, err := sql.Open("sqlite3", source); err == nil {
return db, nil
} else {
return nil, err
}
}
// GetChars returns the security char for this type of database.
func (d *DriverSqlite) GetChars() (charLeft string, charRight string) {
return "`", "`"
}
// HandleSqlBeforeCommit deals with the sql string before commits it to underlying sql driver.
// TODO 需要增加对Save方法的支持可使用正则来实现替换
// TODO 将ON DUPLICATE KEY UPDATE触发器修改为两条SQL语句(INSERT OR IGNORE & UPDATE)
func (d *DriverSqlite) HandleSqlBeforeCommit(link Link, sql string, args []interface{}) (string, []interface{}) {
return sql, args
}
// Tables retrieves and returns the tables of current schema.
// It's mainly used in cli tool chain for automatically generating the models.
func (d *DriverSqlite) Tables(schema ...string) (tables []string, err error) {
var result Result
link, err := d.DB.GetSlave(schema...)
if err != nil {
return nil, err
}
result, err = d.DB.DoGetAll(link, `SELECT NAME FROM SQLITE_MASTER WHERE TYPE='table' ORDER BY NAME`)
if err != nil {
return
}
for _, m := range result {
for _, v := range m {
tables = append(tables, v.String())
}
}
return
}
// TableFields retrieves and returns the fields information of specified table of current schema.
func (d *DriverSqlite) TableFields(table string, schema ...string) (fields map[string]*TableField, err error) {
table = gstr.Trim(table)
if gstr.Contains(table, " ") {
panic("function TableFields supports only single table operations")
}
checkSchema := d.DB.GetSchema()
if len(schema) > 0 && schema[0] != "" {
checkSchema = schema[0]
}
v := d.DB.GetCache().GetOrSetFunc(
fmt.Sprintf(`sqlite_table_fields_%s_%s`, table, checkSchema), func() interface{} {
var result Result
var link *sql.DB
link, err = d.DB.GetSlave(checkSchema)
if err != nil {
return nil
}
result, err = d.DB.DoGetAll(link, fmt.Sprintf(`PRAGMA TABLE_INFO(%s)`, table))
if err != nil {
return nil
}
fields = make(map[string]*TableField)
for i, m := range result {
fields[strings.ToLower(m["name"].String())] = &TableField{
Index: i,
Name: strings.ToLower(m["name"].String()),
Type: strings.ToLower(m["type"].String()),
}
}
return fields
}, 0)
if err == nil {
fields = v.(map[string]*TableField)
}
return
}

View File

@ -8,10 +8,10 @@ package gdb
import (
"bytes"
"database/sql"
"errors"
"fmt"
"github.com/gogf/gf/internal/empty"
"github.com/gogf/gf/internal/utils"
"github.com/gogf/gf/os/gtime"
"reflect"
"regexp"
@ -40,6 +40,11 @@ type apiInterfaces interface {
Interfaces() []interface{}
}
// apiMapStrAny is the interface support for converting struct parameter to map.
type apiMapStrAny interface {
MapStrAny() map[string]interface{}
}
const (
ORM_TAG_FOR_STRUCT = "orm"
ORM_TAG_FOR_UNIQUE = "unique"
@ -51,21 +56,74 @@ var (
quoteWordReg = regexp.MustCompile(`^[a-zA-Z0-9\-_]+$`)
)
// handleTableName adds prefix string and quote chars for the table. It handles table string like:
// "user", "user u", "user,user_detail", "user u, user_detail ut", "user as u, user_detail as ut", "user.user u".
// GetInsertOperationByOption returns proper insert option with given parameter <option>.
func GetInsertOperationByOption(option int) string {
var operator string
switch option {
case gINSERT_OPTION_REPLACE:
operator = "REPLACE"
case gINSERT_OPTION_IGNORE:
operator = "INSERT IGNORE"
default:
operator = "INSERT"
}
return operator
}
// DataToMapDeep converts struct object to map type recursively.
func DataToMapDeep(obj interface{}) map[string]interface{} {
data := gconv.Map(obj, ORM_TAG_FOR_STRUCT)
for key, value := range data {
rv := reflect.ValueOf(value)
kind := rv.Kind()
if kind == reflect.Ptr {
rv = rv.Elem()
kind = rv.Kind()
}
switch kind {
case reflect.Struct:
// The underlying driver supports time.Time/*time.Time types.
if _, ok := value.(time.Time); ok {
continue
}
if _, ok := value.(*time.Time); ok {
continue
}
// Use string conversion in default.
if s, ok := value.(apiString); ok {
data[key] = s.String()
continue
}
delete(data, key)
for k, v := range DataToMapDeep(value) {
data[k] = v
}
}
}
return data
}
// doHandleTableName adds prefix string and quote chars for the table. It handles table string like:
// "user", "user u", "user,user_detail", "user u, user_detail ut", "user as u, user_detail as ut",
// "user.user u", "`user`.`user` u".
//
// Note that, this will automatically checks the table prefix whether already added, if true it does
// nothing to the table name, or else adds the prefix to the table name.
func doHandleTableName(table, prefix, charLeft, charRight string) string {
index := 0
array1 := gstr.SplitAndTrim(table, ",")
var (
index = 0
chars = charLeft + charRight
array1 = gstr.SplitAndTrim(table, ",")
)
for k1, v1 := range array1 {
array2 := gstr.SplitAndTrim(v1, " ")
// Trim the security chars.
array2[0] = gstr.TrimLeftStr(array2[0], charLeft)
array2[0] = gstr.TrimRightStr(array2[0], charRight)
array2[0] = gstr.Trim(array2[0], chars)
// Check whether it has database name.
array3 := gstr.Split(gstr.Trim(array2[0]), ".")
for k, v := range array3 {
array3[k] = gstr.Trim(v, chars)
}
index = len(array3) - 1
// If the table name already has the prefix, skips the prefix adding.
if len(array3[index]) <= len(prefix) || array3[index][:len(prefix)] != prefix {
@ -174,11 +232,11 @@ func GetPrimaryKeyCondition(primary string, where ...interface{}) (newWhereCondi
return where
}
// formatQuery formats the query string and its arguments before executing.
// formatSql formats the sql string and its arguments before executing.
// The internal handleArguments function might be called twice during the SQL procedure,
// but do not worry about it, it's safe and efficient.
func formatQuery(query string, args []interface{}) (newQuery string, newArgs []interface{}) {
return handleArguments(query, args)
func formatSql(sql string, args []interface{}) (newQuery string, newArgs []interface{}) {
return handleArguments(sql, args)
}
// formatWhere formats where statement and its arguments.
@ -196,7 +254,7 @@ func formatWhere(db DB, where interface{}, args []interface{}, omitEmpty bool) (
newArgs = formatWhereInterfaces(db, gconv.Interfaces(where), buffer, newArgs)
case reflect.Map:
for key, value := range varToMapDeep(where) {
for key, value := range DataToMapDeep(where) {
if omitEmpty && empty.IsEmpty(value) {
continue
}
@ -218,7 +276,7 @@ func formatWhere(db DB, where interface{}, args []interface{}, omitEmpty bool) (
})
break
}
for key, value := range varToMapDeep(where) {
for key, value := range DataToMapDeep(where) {
if omitEmpty && empty.IsEmpty(value) {
continue
}
@ -235,12 +293,25 @@ func formatWhere(db DB, where interface{}, args []interface{}, omitEmpty bool) (
newArgs = append(newArgs, args...)
newWhere = buffer.String()
if len(newArgs) > 0 {
// It supports formats like: Where/And/Or("uid", 1) , Where/And/Or("uid>=", 1)
if gstr.Pos(newWhere, "?") == -1 {
if lastOperatorReg.MatchString(newWhere) {
// Eg: Where/And/Or("uid>=", 1)
newWhere += "?"
} else if gregex.IsMatchString(`^[\w\.\-]+$`, newWhere) {
newWhere += "=?"
newWhere = db.QuoteString(newWhere)
if len(newArgs) > 0 {
if utils.IsArray(newArgs[0]) {
// Eg: Where("id", []int{1,2,3})
newWhere += " IN (?)"
} else if empty.IsNil(newArgs[0]) {
// Eg: Where("id", nil)
newWhere += " IS NULL"
newArgs = nil
} else {
// Eg: Where/And/Or("uid", 1)
newWhere += "=?"
}
}
}
}
}
@ -269,7 +340,7 @@ func formatWhereInterfaces(db DB, where []interface{}, buffer *bytes.Buffer, new
// formatWhereKeyValue handles each key-value pair of the parameter map.
func formatWhereKeyValue(db DB, buffer *bytes.Buffer, newArgs []interface{}, key string, value interface{}) []interface{} {
key = db.quoteWord(key)
quotedKey := db.QuoteWord(key)
if buffer.Len() > 0 {
buffer.WriteString(" AND ")
}
@ -277,36 +348,43 @@ func formatWhereKeyValue(db DB, buffer *bytes.Buffer, newArgs []interface{}, key
// the key string, it automatically adds '?' holder chars according to its arguments count
// and converts it to "IN" statement.
rv := reflect.ValueOf(value)
switch rv.Kind() {
kind := rv.Kind()
switch kind {
case reflect.Slice, reflect.Array:
count := gstr.Count(key, "?")
count := gstr.Count(quotedKey, "?")
if count == 0 {
buffer.WriteString(key + " IN(?)")
buffer.WriteString(quotedKey + " IN(?)")
newArgs = append(newArgs, value)
} else if count != rv.Len() {
buffer.WriteString(key)
buffer.WriteString(quotedKey)
newArgs = append(newArgs, value)
} else {
buffer.WriteString(key)
buffer.WriteString(quotedKey)
newArgs = append(newArgs, gconv.Interfaces(value)...)
}
default:
if value == nil {
buffer.WriteString(key)
if value == nil || empty.IsNil(rv) {
if gregex.IsMatchString(`^[\w\.\-]+$`, key) {
// The key is a single field name.
buffer.WriteString(quotedKey + " IS NULL")
} else {
// The key may have operation chars.
buffer.WriteString(quotedKey)
}
} else {
// It also supports "LIKE" statement, which we considers it an operator.
key = gstr.Trim(key)
if gstr.Pos(key, "?") == -1 {
quotedKey = gstr.Trim(quotedKey)
if gstr.Pos(quotedKey, "?") == -1 {
like := " like"
if len(key) > len(like) && gstr.Equal(key[len(key)-len(like):], like) {
buffer.WriteString(key + " ?")
} else if lastOperatorReg.MatchString(key) {
buffer.WriteString(key + " ?")
if len(quotedKey) > len(like) && gstr.Equal(quotedKey[len(quotedKey)-len(like):], like) {
buffer.WriteString(quotedKey + " ?")
} else if lastOperatorReg.MatchString(quotedKey) {
buffer.WriteString(quotedKey + " ?")
} else {
buffer.WriteString(key + "=?")
buffer.WriteString(quotedKey + "=?")
}
} else {
buffer.WriteString(key)
buffer.WriteString(quotedKey)
}
newArgs = append(newArgs, value)
}
@ -314,43 +392,10 @@ func formatWhereKeyValue(db DB, buffer *bytes.Buffer, newArgs []interface{}, key
return newArgs
}
// varToMapDeep converts struct object to map type recursively.
func varToMapDeep(obj interface{}) map[string]interface{} {
data := gconv.Map(obj, ORM_TAG_FOR_STRUCT)
for key, value := range data {
rv := reflect.ValueOf(value)
kind := rv.Kind()
if kind == reflect.Ptr {
rv = rv.Elem()
kind = rv.Kind()
}
switch kind {
case reflect.Struct:
// The underlying driver supports time.Time/*time.Time types.
if _, ok := value.(time.Time); ok {
continue
}
if _, ok := value.(*time.Time); ok {
continue
}
// Use string conversion in default.
if s, ok := value.(apiString); ok {
data[key] = s.String()
continue
}
delete(data, key)
for k, v := range varToMapDeep(value) {
data[k] = v
}
}
}
return data
}
// handleArguments is a nice function which handles the query and its arguments before committing to
// underlying driver.
func handleArguments(query string, args []interface{}) (newQuery string, newArgs []interface{}) {
newQuery = query
func handleArguments(sql string, args []interface{}) (newSql string, newArgs []interface{}) {
newSql = sql
// Handles the slice arguments.
if len(args) > 0 {
for index, arg := range args {
@ -374,12 +419,12 @@ func handleArguments(query string, args []interface{}) (newQuery string, newArgs
// It the '?' holder count equals the length of the slice,
// it does not implement the arguments splitting logic.
// Eg: db.Query("SELECT ?+?", g.Slice{1, 2})
if len(args) == 1 && gstr.Count(newQuery, "?") == rv.Len() {
if len(args) == 1 && gstr.Count(newSql, "?") == rv.Len() {
break
}
// counter is used to finding the inserting position for the '?' holder.
counter := 0
newQuery, _ = gregex.ReplaceStringFunc(`\?`, newQuery, func(s string) string {
newSql, _ = gregex.ReplaceStringFunc(`\?`, newSql, func(s string) string {
counter++
if counter == index+1 {
return "?" + strings.Repeat(",?", rv.Len()-1)
@ -415,59 +460,46 @@ func handleArguments(query string, args []interface{}) (newQuery string, newArgs
}
// formatError customizes and returns the SQL error.
func formatError(err error, query string, args ...interface{}) error {
if err != nil && err != sql.ErrNoRows {
return errors.New(fmt.Sprintf("%s, %s\n", err.Error(), bindArgsToQuery(query, args)))
func formatError(err error, sql string, args ...interface{}) error {
if err != nil && err != ErrNoRows {
return errors.New(fmt.Sprintf("%s, %s\n", err.Error(), FormatSqlWithArgs(sql, args)))
}
return err
}
// getInsertOperationByOption returns proper insert option with given parameter <option>.
func getInsertOperationByOption(option int) string {
var operator string
switch option {
case gINSERT_OPTION_REPLACE:
operator = "REPLACE"
case gINSERT_OPTION_IGNORE:
operator = "INSERT IGNORE"
default:
operator = "INSERT"
}
return operator
}
// bindArgsToQuery binds the arguments to the query string and returns a complete
// FormatSqlWithArgs binds the arguments to the sql string and returns a complete
// sql string, just for debugging.
func bindArgsToQuery(query string, args []interface{}) string {
func FormatSqlWithArgs(sql string, args []interface{}) string {
index := -1
newQuery, _ := gregex.ReplaceStringFunc(`\?`, query, func(s string) string {
index++
if len(args) > index {
if args[index] == nil {
return "null"
}
rv := reflect.ValueOf(args[index])
kind := rv.Kind()
if kind == reflect.Ptr {
if rv.IsNil() || !rv.IsValid() {
newQuery, _ := gregex.ReplaceStringFunc(
`(\?|:\d+|\$\d+|@p\d+)`, sql, func(s string) string {
index++
if len(args) > index {
if args[index] == nil {
return "null"
}
rv = rv.Elem()
kind = rv.Kind()
}
switch kind {
case reflect.String, reflect.Map, reflect.Slice, reflect.Array:
return `'` + gstr.QuoteMeta(gconv.String(args[index]), `'`) + `'`
case reflect.Struct:
if t, ok := args[index].(time.Time); ok {
return `'` + gtime.NewFromTime(t).String() + `'`
rv := reflect.ValueOf(args[index])
kind := rv.Kind()
if kind == reflect.Ptr {
if rv.IsNil() || !rv.IsValid() {
return "null"
}
rv = rv.Elem()
kind = rv.Kind()
}
return `'` + gstr.QuoteMeta(gconv.String(args[index]), `'`) + `'`
switch kind {
case reflect.String, reflect.Map, reflect.Slice, reflect.Array:
return `'` + gstr.QuoteMeta(gconv.String(args[index]), `'`) + `'`
case reflect.Struct:
if t, ok := args[index].(time.Time); ok {
return `'` + gtime.NewFromTime(t).String() + `'`
}
return `'` + gstr.QuoteMeta(gconv.String(args[index]), `'`) + `'`
}
return gconv.String(args[index])
}
return gconv.String(args[index])
}
return s
})
return s
})
return newQuery
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More