Compare commits

...

203 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
6e1f8c3cfc version updates 2020-02-29 08:54:18 +08:00
e58d7e8dda add internal log for gi18n; improve unit testing case for ghttp.Server 2020-02-28 23:00:05 +08:00
3a3384cf06 Merge branch 'master' of https://github.com/gogf/gf 2020-02-27 17:09:44 +08:00
ef2a9f6fd1 fix issue in log paatern for ghttp.Server 2020-02-27 17:09:12 +08:00
63f756f731 Merge pull request #514 from kevinlincg/master
fix typo in gpool_bench_test.go
2020-02-26 23:38:33 +08:00
bb1c27c36a add more unit testing cases for glog 2020-02-26 23:26:24 +08:00
87cd0703c0 change internal log prefix from '[GF]' to '[INTE]' 2020-02-26 11:57:26 +08:00
6317d9de53 add ci for golang v1.14 2020-02-26 11:54:46 +08:00
7acf16fdba add UploadFile feature for ghttp.Server 2020-02-26 01:01:28 +08:00
a52b454d3e add UploadFile feature for ghttp.Server 2020-02-26 00:48:27 +08:00
816e075c52 add more unit testing cases for package garray 2020-02-25 23:19:37 +08:00
9882b361a8 add more unit testing cases for package gstr 2020-02-25 23:01:51 +08:00
4415dcf1c1 add HasPrefix/HasSuffix for package gstr 2020-02-25 21:03:07 +08:00
42fd583bfd add more inernal logging points for core components 2020-02-24 21:09:19 +08:00
c70bc7c96a improve pakage g/gins 2020-02-23 20:25:55 +08:00
02bd780a33 readme and donator update 2020-02-22 17:06:58 +08:00
24a2192ce2 README updates 2020-02-22 15:36:31 +08:00
d8ef8a1f5d add gf.debug options and GF_DEBUG env control params for internal logging feature 2020-02-22 14:51:44 +08:00
745a913cfb add FilterNil/FilterEmpty functions for package garray; add FieldsStr/FieldsExStr for gdb.Model 2020-02-22 14:26:36 +08:00
13dba407a2 fix parameter issue in benchmark of internal/rwmutex 2020-02-21 13:15:40 +08:00
34e7c5f809 rename grand.Str to grand.S; add different function Str for grand 2020-02-21 00:01:27 +08:00
d570624caa fix typo in gpool_bench_test.go 2020-02-20 09:01:09 +08:00
f18312419b improve CORS feature for ghttp.Server 2020-02-16 23:18:37 +08:00
89f869dd44 remove internal logging for gsession.StorageFile; improve example codes for CORS feature of ghttp.Server 2020-02-16 23:00:42 +08:00
20b64507b1 improve string conversion for gtime.Time 2020-02-16 22:39:12 +08:00
7443246e05 add gtime.TimeWrapper 2020-02-16 18:07:05 +08:00
f9e7823c14 improve configuration for package gdb 2020-02-16 16:36:39 +08:00
52943b283c go.mod updates; add search path configuration in file for package ghttp.Server 2020-02-16 16:34:30 +08:00
36403fdc08 improve configuration for mssql 2020-02-16 16:25:03 +08:00
0317f6812e add more unit testing cases for gtime 2020-02-16 15:11:21 +08:00
5169137069 improve unit testing case for CORS feature for package ghttp 2020-02-16 13:32:06 +08:00
7d9bccf912 README updates 2020-02-15 12:00:20 +08:00
14f56ea18f donator updates 2020-02-14 22:21:53 +08:00
1736d271d2 add more unit testing case 2020-02-14 22:13:41 +08:00
19755ad233 improve gcfg 2020-02-14 21:57:35 +08:00
cfdd043e4e add OctStr function for gstr 2020-02-12 10:48:15 +08:00
78917ed5cb comment updates for package ghttp 2020-02-11 10:00:10 +08:00
88684ca00a add panic if internal watcher creation fails for gfsnotify; improve codes and change comment from chinese to english for gdb 2020-02-10 20:37:53 +08:00
784983806a add InserIgnore feature for package gdb 2020-02-08 23:46:10 +08:00
cdb3b94e22 add NewWithTag function for gjson/gparser 2020-02-08 14:07:32 +08:00
83dcc4a5e0 fix issue for overwriting the route item if allowed 2020-02-08 11:17:09 +08:00
a6c0b281a3 add struct support for where condition statement of gdb 2020-02-07 20:58:47 +08:00
3120f24553 add struct support for where condition statement og gdb 2020-02-07 19:44:11 +08:00
ac9be6134b add global schema access support for mssql in gdb 2020-02-07 17:21:05 +08:00
4c1b4f7858 change time measuing unit from microtime to millitime for ghttp.Request; change graceful reload feature from true to false in default 2020-02-07 16:29:14 +08:00
1e45bf93d8 remove error printing when decoding error in communication feature of gproc 2020-02-06 19:21:17 +08:00
e8dd3979b6 add more unit testing cases for ghttp/gview 2020-02-06 15:17:10 +08:00
374ee4c0ea improve ghttp.Request for making the request body reusable for multiple times 2020-02-06 11:22:36 +08:00
95411aff77 improve ghttp.Request for making the request body reusable for multiple times 2020-02-06 11:14:38 +08:00
1999ef95c1 fix issue in gconv.Struct* functions panic when converting attribute value is nil 2020-02-05 22:06:24 +08:00
b15075fdfe fix issue in gconv.Struct* functions panic when converting attribute value is nil 2020-02-05 22:02:49 +08:00
4d2b244319 fix issue in gres.UnpackContent; fix issue in gtime.NewFromTimeStamp 2020-02-04 17:09:18 +08:00
4c3af63076 improve time string parsing for invalid datetime 2020-02-01 20:14:24 +08:00
91bbff6ced architecture updates 2020-01-23 15:04:12 +08:00
26aab44ec8 fix issue in char '-' support for parameter retrieving for ghttp.Request 2020-01-22 20:28:42 +08:00
2e10ce421b improve plugin feature 2020-01-21 22:18:49 +08:00
8eda69b11e improve the plugin feature for ghttp.Server 2020-01-21 17:18:03 +08:00
7d7b242968 Merge branch 'master' of https://github.com/gogf/gf 2020-01-21 15:42:19 +08:00
202419202f improve logger feautre, add unit testing cases for ghttp.Server; add SetDefaultLogger function for glog 2020-01-21 15:42:08 +08:00
55078beed1 Merge pull request #484 from chikaku/remove_redundant
Remove redundant code in gsession
2020-01-21 15:40:35 +08:00
d9f4e6eaa6 remove redundant code in gsession 2020-01-21 14:55:08 +08:00
2ba0913bea comment update for gtimer 2020-01-21 14:46:23 +08:00
8f2dcf21ff improve gconv.Map 2020-01-20 21:25:55 +08:00
01b06e0745 improve ghttp.BuildParams 2020-01-20 20:32:39 +08:00
665b5960c8 fix issue in minus number converting for gconv.Int 2020-01-20 20:18:24 +08:00
eb6a7a4728 add function UnmarshalValue feature for package garray/gmap/gset/gtype/gvar/gjson/gconv 2020-01-20 19:56:42 +08:00
7df53ff55e rename all timestamp function names from *Second to Timestamp* 2020-01-20 14:14:11 +08:00
8021f39710 version updates 2020-01-19 21:21:41 +08:00
f2af08270b improve gproc 2020-01-19 20:42:21 +08:00
c2f028848c readme updates 2020-01-18 22:35:07 +08:00
d9c7224861 readme updates 2020-01-18 22:21:37 +08:00
f59a1ada88 improve static service feature, add plugin feature for ghttp.Server 2020-01-17 21:12:52 +08:00
705ab1d33f improve garray; add RemoveValue function for garray 2020-01-17 19:48:50 +08:00
c07c4d7217 version updates 2020-01-16 21:26:34 +08:00
b867b2a0bc add return parameter name for function Cas of gtype;improve Response.Redirect* functions by adding optional parameter code 2020-01-16 21:04:28 +08:00
872d674182 fix issue in database 'time' type support in package gdb 2020-01-15 21:23:40 +08:00
4682abafdf fix concurrent issue in gdb.Model.Count 2020-01-15 10:38:02 +08:00
b7d194cf52 improva gcmd.Parser/gres 2020-01-15 09:36:58 +08:00
edf2366296 improve gzip feature for gcompress; add gzip compression for package gres 2020-01-15 00:15:56 +08:00
22af5be71f rename parameter name for gipv4.Ip2Long/Long2Ip 2020-01-13 14:50:06 +08:00
f662ff8051 add pprof unit testing case for ghttp; reame updates 2020-01-12 22:26:07 +08:00
536 changed files with 27044 additions and 17071 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

@ -1,8 +1,3 @@
[database]
type = "mssql"
host = "127.0.0.1"
port = "1451"
user = "sa"
pass = "eno@123"
name = "frpc"
linkinfo = "mssql:user id=test;password=test1;server=122.152.202.91;port=1433;database=test;encrypt=disable"

View File

@ -2,13 +2,22 @@ package main
import (
"fmt"
"github.com/gogf/gf/os/gtime"
_ "github.com/denisenkom/go-mssqldb"
"github.com/gogf/gf/frame/g"
)
func main() {
r, err := g.DB().GetAll(`SELECT TOP 10 * FROM KF_PatInfo_Emergency`)
fmt.Println(err)
g.Dump(r.ToList())
type Table2 struct {
Id string `orm:"id;pr" json:"id"` //ID
Createtime gtime.Time `orm:"createtime" json:"createtime"` //创建时间
Updatetime gtime.Time `orm:"updatetime" json:"updatetime"` //更新时间
}
var table2 Table2
err := g.DB().Table("table2").Where("id=?", 1).Struct(&table2)
if err != nil {
panic(err)
}
fmt.Println(table2.Createtime)
}

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

@ -0,0 +1,18 @@
package main
import (
"fmt"
"github.com/gogf/gf/frame/g"
"time"
)
func main() {
db := g.DB()
db.SetDebug(true)
for {
r, err := db.Table("user").All()
fmt.Println(err)
fmt.Println(r)
time.Sleep(time.Second * 10)
}
}

View File

@ -8,10 +8,5 @@ func main() {
db := g.DB()
db.SetDebug(true)
one, e := db.Table("order.order o").LeftJoin("user.user u", "o.uid=u.id").Where("u.id", 1).One()
if e != nil {
panic(e)
}
g.Dump(one)
db.Table("user").Fields("DISTINCT id,nickname").Filter().All()
}

View File

@ -100,53 +100,53 @@ func testConvert() {
func testSplitChar() {
var v interface{}
j := gjson.New(nil)
t1 := gtime.Nanosecond()
t1 := gtime.TimestampNano()
j.Set("a.b.c.d.e.f.g.h.i.j.k", 1)
t2 := gtime.Nanosecond()
t2 := gtime.TimestampNano()
fmt.Println(t2 - t1)
t5 := gtime.Nanosecond()
t5 := gtime.TimestampNano()
v = j.Get("a.b.c.d.e.f.g.h.i.j.k")
t6 := gtime.Nanosecond()
t6 := gtime.TimestampNano()
fmt.Println(v)
fmt.Println(t6 - t5)
j.SetSplitChar('#')
t7 := gtime.Nanosecond()
t7 := gtime.TimestampNano()
v = j.Get("a#b#c#d#e#f#g#h#i#j#k")
t8 := gtime.Nanosecond()
t8 := gtime.TimestampNano()
fmt.Println(v)
fmt.Println(t8 - t7)
}
func testViolenceCheck() {
j := gjson.New(nil)
t1 := gtime.Nanosecond()
t1 := gtime.TimestampNano()
j.Set("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a", 1)
t2 := gtime.Nanosecond()
t2 := gtime.TimestampNano()
fmt.Println(t2 - t1)
t3 := gtime.Nanosecond()
t3 := gtime.TimestampNano()
j.Set("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a", 1)
t4 := gtime.Nanosecond()
t4 := gtime.TimestampNano()
fmt.Println(t4 - t3)
t5 := gtime.Nanosecond()
t5 := gtime.TimestampNano()
j.Get("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a")
t6 := gtime.Nanosecond()
t6 := gtime.TimestampNano()
fmt.Println(t6 - t5)
j.SetViolenceCheck(false)
t7 := gtime.Nanosecond()
t7 := gtime.TimestampNano()
j.Set("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a", 1)
t8 := gtime.Nanosecond()
t8 := gtime.TimestampNano()
fmt.Println(t8 - t7)
t9 := gtime.Nanosecond()
t9 := gtime.TimestampNano()
j.Get("a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a")
t10 := gtime.Nanosecond()
t10 := gtime.TimestampNano()
fmt.Println(t10 - t9)
}

View File

@ -3,34 +3,16 @@ package main
import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
"github.com/gogf/gf/os/gfile"
"io"
)
// Upload uploads files to /tmp .
func Upload(r *ghttp.Request) {
saveDir := "/tmp/"
for _, item := range r.GetMultipartFiles("upload-file") {
file, err := item.Open()
if err != nil {
r.Response.Write(err)
return
}
defer file.Close()
f, err := gfile.Create(saveDir + gfile.Basename(item.Filename))
if err != nil {
r.Response.Write(err)
return
}
defer f.Close()
if _, err := io.Copy(f, file); err != nil {
r.Response.Write(err)
return
}
saveDirPath := "/tmp/"
files := r.GetUploadFiles("upload-file")
if err := files.Save(saveDirPath); err != nil {
r.Response.WriteExit(err)
}
r.Response.Write("upload successfully")
r.Response.WriteExit("upload successfully")
}
// UploadShow shows uploading simgle file page.
@ -71,7 +53,7 @@ func UploadShowBatch(r *ghttp.Request) {
func main() {
s := g.Server()
s.Group("/upload", func(group *ghttp.RouterGroup) {
group.ALL("/", Upload)
group.POST("/", Upload)
group.ALL("/show", UploadShow)
group.ALL("/batch", UploadShowBatch)
})

View File

@ -3,34 +3,16 @@ package main
import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
"github.com/gogf/gf/os/gfile"
"io"
)
// Upload uploads files to /tmp .
func Upload(r *ghttp.Request) {
saveDir := "/tmp/"
for _, item := range r.GetMultipartFiles("upload-file") {
file, err := item.Open()
if err != nil {
r.Response.Write(err)
return
}
defer file.Close()
f, err := gfile.Create(saveDir + gfile.Basename(item.Filename))
if err != nil {
r.Response.Write(err)
return
}
defer f.Close()
if _, err := io.Copy(f, file); err != nil {
r.Response.Write(err)
return
}
saveDirPath := "/tmp/"
files := r.GetUploadFiles("upload-file")
if err := files.Save(saveDirPath); err != nil {
r.Response.WriteExit(err)
}
r.Response.Write("upload successfully")
r.Response.WriteExit("upload successfully")
}
// UploadShow shows uploading simgle file page.
@ -71,7 +53,7 @@ func UploadShowBatch(r *ghttp.Request) {
func main() {
s := g.Server()
s.Group("/upload", func(group *ghttp.RouterGroup) {
group.ALL("/", Upload)
group.POST("/", Upload)
group.ALL("/show", UploadShow)
group.ALL("/batch", UploadShowBatch)
})

View File

@ -0,0 +1,22 @@
package main
import (
"fmt"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
"io/ioutil"
)
func main() {
s := g.Server()
s.SetIndexFolder(true)
s.BindHandler("/", func(r *ghttp.Request) {
body1 := r.GetBody()
body2, _ := ioutil.ReadAll(r.Body)
fmt.Println(body1)
fmt.Println(body2)
r.Response.Write("hello world")
})
s.SetPort(8999)
s.Run()
}

View File

@ -3,6 +3,7 @@ package main
import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
"github.com/gogf/gf/os/glog"
)
func MiddlewareCORS(r *ghttp.Request) {
@ -11,6 +12,7 @@ func MiddlewareCORS(r *ghttp.Request) {
}
func Order(r *ghttp.Request) {
glog.Println("order")
r.Response.Write("GET")
}
@ -18,7 +20,7 @@ func main() {
s := g.Server()
s.Group("/api.v1", func(group *ghttp.RouterGroup) {
group.Middleware(MiddlewareCORS)
g.GET("/order", Order)
group.GET("/order", Order)
})
s.SetPort(8199)
s.Run()

View File

@ -20,7 +20,7 @@ func main() {
s := g.Server()
s.Group("/api.v1", func(group *ghttp.RouterGroup) {
group.Middleware(MiddlewareCORS)
g.GET("/order", Order)
group.GET("/order", Order)
})
s.SetPort(8199)
s.Run()

View File

@ -26,7 +26,7 @@ func main() {
s := g.Server()
s.Group("/api.v1", func(group *ghttp.RouterGroup) {
group.Middleware(MiddlewareCORS)
g.GET("/order", Order)
group.GET("/order", Order)
})
s.SetPort(8199)
s.Run()

View File

@ -19,7 +19,7 @@ func MiddlewareAuth(r *ghttp.Request) {
func main() {
s := g.Server()
s.Group("/admin", func(group *ghttp.RouterGroup) {
g.MiddlewarePattern("/*action", func(r *ghttp.Request) {
group.Middleware(func(r *ghttp.Request) {
if action := r.GetRouterString("action"); action != "" {
switch action {
case "login":

View File

@ -25,14 +25,12 @@ func MiddlewareCORS(r *ghttp.Request) {
func MiddlewareLog(r *ghttp.Request) {
r.Middleware.Next()
glog.Println(r.Response.Status, r.URL.Path)
g.Log().Println(r.Response.Status, r.URL.Path)
}
func main() {
s := g.Server()
s.Group("/", func(group *ghttp.RouterGroup) {
group.Middleware(MiddlewareLog)
})
s.Use(MiddlewareLog)
s.Group("/api.v2", func(group *ghttp.RouterGroup) {
group.Middleware(MiddlewareAuth, MiddlewareCORS)
group.ALL("/user/list", func(r *ghttp.Request) {

View File

@ -13,20 +13,20 @@ func main() {
r.Middleware.Next()
r.Response.Write("end")
})
g.Group("/order", func(group *ghttp.RouterGroup) {
g.GET("/list", func(r *ghttp.Request) {
group.Group("/order", func(group *ghttp.RouterGroup) {
group.GET("/list", func(r *ghttp.Request) {
r.Response.Write("list")
})
})
g.Group("/user", func(group *ghttp.RouterGroup) {
g.GET("/info", func(r *ghttp.Request) {
group.Group("/user", func(group *ghttp.RouterGroup) {
group.GET("/info", func(r *ghttp.Request) {
r.Response.Write("info")
})
g.POST("/edit", func(r *ghttp.Request) {
group.POST("/edit", func(r *ghttp.Request) {
r.Response.Write("edit")
})
})
g.Group("/hook", func(group *ghttp.RouterGroup) {
group.Group("/hook", func(group *ghttp.RouterGroup) {
group.Hook("/*", ghttp.HOOK_BEFORE_SERVE, func(r *ghttp.Request) {
r.Response.Write("hook any")
})

View File

@ -9,14 +9,14 @@ import (
func main() {
s := g.Server()
s.Group("/", func(group *ghttp.RouterGroup) {
g.GET("/set", func(r *ghttp.Request) {
r.Session.Set("time", gtime.Second())
group.GET("/set", func(r *ghttp.Request) {
r.Session.Set("time", gtime.Timestamp())
r.Response.Write("ok")
})
g.GET("/get", func(r *ghttp.Request) {
group.GET("/get", func(r *ghttp.Request) {
r.Response.WriteJson(r.Session.Map())
})
g.GET("/clear", func(r *ghttp.Request) {
group.GET("/clear", func(r *ghttp.Request) {
r.Session.Clear()
})
})

View File

@ -0,0 +1,29 @@
package main
import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/net/ghttp"
"github.com/gogf/gf/os/gsession"
"github.com/gogf/gf/os/gtime"
"time"
)
func main() {
s := g.Server()
s.SetSessionMaxAge(2 * time.Minute)
s.SetSessionStorage(gsession.NewStorageRedis(g.Redis()))
s.Group("/", func(group *ghttp.RouterGroup) {
group.GET("/set", func(r *ghttp.Request) {
r.Session.Set("time", gtime.Timestamp())
r.Response.Write("ok")
})
group.GET("/get", func(r *ghttp.Request) {
r.Response.WriteJson(r.Session.Map())
})
group.GET("/clear", func(r *ghttp.Request) {
r.Session.Clear()
})
})
s.SetPort(8199)
s.Run()
}

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

@ -27,7 +27,7 @@ func main() {
},
MemUsed: 15560320,
MemTotal: 16333788,
Time: int(gtime.Second()),
Time: int(gtime.Timestamp()),
})
if err != nil {
panic(err)

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

@ -9,7 +9,7 @@ import (
)
func main() {
start := gtime.Millisecond()
start := gtime.TimestampMilli()
wg := sync.WaitGroup{}
for i := 0; i < 100000; i++ {
wg.Add(1)
@ -19,5 +19,5 @@ func main() {
}()
}
wg.Wait()
fmt.Println("time spent:", gtime.Millisecond()-start)
fmt.Println("time spent:", gtime.TimestampMilli()-start)
}

View File

@ -10,7 +10,7 @@ import (
)
func main() {
start := gtime.Millisecond()
start := gtime.TimestampMilli()
wg := sync.WaitGroup{}
for i := 0; i < 100000; i++ {
wg.Add(1)
@ -21,5 +21,5 @@ func main() {
}
wg.Wait()
fmt.Println(grpool.Size())
fmt.Println("time spent:", gtime.Millisecond()-start)
fmt.Println("time spent:", gtime.TimestampMilli()-start)
}

View File

@ -9,8 +9,8 @@ import (
func main() {
fmt.Println("Date :", gtime.Date())
fmt.Println("Datetime :", gtime.Datetime())
fmt.Println("Second :", gtime.Second())
fmt.Println("Millisecond:", gtime.Millisecond())
fmt.Println("Microsecond:", gtime.Microsecond())
fmt.Println("Nanosecond :", gtime.Nanosecond())
fmt.Println("Second :", gtime.Timestamp())
fmt.Println("Millisecond:", gtime.TimestampMilli())
fmt.Println("Microsecond:", gtime.TimestampMicro())
fmt.Println("Nanosecond :", gtime.TimestampNano())
}

View File

@ -5,4 +5,14 @@
[redis]
default = "127.0.0.1:6379,0"
cache = "127.0.0.1:6379,1"
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,14 +1,25 @@
package main
import (
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/crypto/gaes"
"github.com/gogf/gf/os/gfile"
"github.com/gogf/gf/os/gres"
)
var (
CryptoKey = []byte("x76cgqt36i9c863bzmotuf8626dxiwu0")
)
func main() {
g.Dump(gfile.ScanDirFile("/Users/john/Temp/test", "Dockerfile", true))
//if err := gfile.ReplaceDir("gf-empty", "app", "/Users/john/Temp/test", "*.*", true); err != nil {
// glog.Fatal("content replacing failed,", err.Error())
//}
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,9 +1,8 @@
language: go
go:
- "1.11.x"
- "1.12.x"
- "1.13.x"
- "1.14.x"
branches:
only:
@ -12,7 +11,7 @@ branches:
- staging
env:
- GF_DEV=1 GO111MODULE=on
- GF_DEBUG=1 GO111MODULE=on
services:
- mysql

View File

@ -2,6 +2,7 @@
We currently accept donation by Alipay/WechatPay, please note your github/gitee account in your payment bill.
> If you cannot view the donation image, please click [here](https://goframe.org/images/donate.png).
| Name | Channel | Amount | Comment
|---|---|--- | ---
@ -14,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 |
@ -39,9 +40,35 @@ 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|
|*铁|wechat|¥0.01|
|C*e|wechat|¥66.66| GF越来越好棒👍
|(佚名)|wechat|¥6.66| (名字打不出来也没备注捐赠时间2020-02-21 14:24:34)
|[王飞](https://gitee.com/wang_2018)|gitee|¥20.00| 感谢您的开源项目!
|[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

@ -1,6 +1,6 @@
# GoFrame
[![Go Doc](https://godoc.org/github.com/gogf/gf?status.svg)](https://godoc.org/github.com/gogf/gf/g#pkg-subdirectories)
[![Go Doc](https://godoc.org/github.com/gogf/gf?status.svg)](https://godoc.org/github.com/gogf/gf)
[![Build Status](https://travis-ci.org/gogf/gf.svg?branch=master)](https://travis-ci.org/gogf/gf)
[![Go Report](https://goreportcard.com/badge/github.com/gogf/gf?v=1)](https://goreportcard.com/report/github.com/gogf/gf)
[![Code Coverage](https://codecov.io/gh/gogf/gf/branch/master/graph/badge.svg)](https://codecov.io/gh/gogf/gf/branch/master)
@ -9,11 +9,11 @@
English | [简体中文](README_ZH.MD)
`GF(GoFrame)` is a modular, full-featured and production-ready application development framework of golang.
Providing a series of core components and dozens of practical modules,
`GF(GoFrame)` is a modular, loose-coupled, full-featured and production-ready application development framework of golang,
providing a series of core components and dozens of practical modules,
such as: memcache, configure, validator, logging, array/queue/set/map containers,
timer/timing tasks, file/memory lock, object pool, database ORM, etc.
Supporting web server integrated with router, cookie, session, middleware, logger,
timer/timing tasks, file/memory lock, object pool, database ORM, etc,
supporting web server integrated with router, cookie, session, middleware, logger,
template, https, hooks, rewrites and many more features.
@ -28,7 +28,7 @@ require github.com/gogf/gf latest
# Limitation
```
golang version >= 1.10
golang version >= 1.13
```
# Documentation
@ -36,49 +36,41 @@ golang version >= 1.10
* [APIDoc](https://godoc.org/github.com/gogf/gf)
* [中文文档](https://goframe.org)
# Discussion
- QQ Group[116707870](//shang.qq.com/wpa/qunwpa?idkey=195f91eceeb5d7fa76009b7cd5a4641f70bf4897b7f5a520635eb26ff17adfe7)
- WX GroupAdd friend`389961817` in WeChat, commenting `GF`
- Issueshttps://github.com/gogf/gf/issues
> It's recommended learning `GoFrame` through its awesome source codes and API reference.
# Architecture
<div align=center>
<img src="https://goframe.org/images/arch.png?v=10"/>
<img src="https://goframe.org/images/arch.png?v=11"/>
</div>
# Quick Start
```go
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.Write("Hello World")
})
s.Run()
}
```
[More Features...](https://goframe.org/start/index)
# License
`GF` is licensed under the [MIT License](LICENSE), 100% free and open-source, forever.
# Contributors
This project exists thanks to all the people who contribute. [[Contributors](https://github.com/gogf/gf/graphs/contributors)].
<a href="https://github.com/gogf/gf/graphs/contributors"><img src="https://opencollective.com/goframe/contributors.svg?width=890&button=false" /></a>
# Donators
We currently accept donation by Alipay/WechatPay, please note your github/gitee account in your payment bill. If you like `GF`, why not [buy developer a cup of coffee](DONATOR.MD)?
# Sponsors
We appreciate any kind of sponsorship for `GF` development. If you've got some interesting, please contact WeChat `389961817` / Email `john@goframe.org`.
# Thanks
<a href="https://www.jetbrains.com/?from=GoFrame"><img src="https://goframe.org/images/jetbrains.png" width="100" alt="JetBrains"/></a>
<!--
# Sponsor
We appreciate any kind of sponsorship for `GF` development. If you've got some interested, please contact john@goframe.org.
-->

View File

@ -1,5 +1,5 @@
# GoFrame
[![Go Doc](https://godoc.org/github.com/gogf/gf?status.svg)](https://godoc.org/github.com/gogf/gf/g#pkg-subdirectories)
[![Go Doc](https://godoc.org/github.com/gogf/gf?status.svg)](https://godoc.org/github.com/gogf/gf)
[![Build Status](https://travis-ci.org/gogf/gf.svg?branch=master)](https://travis-ci.org/gogf/gf)
[![Go Report](https://goreportcard.com/badge/github.com/gogf/gf?v=1)](https://goreportcard.com/report/github.com/gogf/gf)
[![Code Coverage](https://codecov.io/gh/gogf/gf/branch/master/graph/badge.svg)](https://codecov.io/gh/gogf/gf/branch/master)
@ -8,21 +8,27 @@
[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等特性。
# 特点
* 模块化、松耦合设计;
* 模块丰富,开箱即用;
* 简便及可维护性为宗旨
* 简便易用,易于维护
* 社区活跃,大牛谦逊低调脾气好;
* 高代码质量、高单元测试覆盖率;
* 详尽的开发文档及示例;
* 完善的本地中文化支持;
* 更适合企业及团队使用;
* 更多请查阅文档及源码;
# 地址
- **主库**https://github.com/gogf/gf
- **码云**https://gitee.com/johng/gf
# 安装
```html
@ -35,12 +41,12 @@ require github.com/gogf/gf latest
# 限制
```shell
golang版本 >= 1.11
golang版本 >= 1.13
```
# 架构
<div align=center>
<img src="https://goframe.org/images/arch.png?v=10"/>
<img src="https://goframe.org/images/arch.png?v=11"/>
</div>
@ -51,35 +57,31 @@ golang版本 >= 1.11
接口文档:[https://godoc.org/github.com/gogf/gf](https://godoc.org/github.com/gogf/gf)
# 使用
```go
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.Write("Hello World")
})
s.Run()
}
```
[更多..](https://goframe.org/start/index)
# 帮助
- QQ交流群[116707870](//shang.qq.com/wpa/qunwpa?idkey=195f91eceeb5d7fa76009b7cd5a4641f70bf4897b7f5a520635eb26ff17adfe7)
- WX交流群微信添加`389961817`备注`GF`
- 主库ISSUEhttps://github.com/gogf/gf/issues
> 建议通过阅读`Gorame`的源码以及API文档深度学习`GoFrame`,了解更多的精妙设计。
# 协议
`GF` 使用非常友好的 [MIT](LICENSE) 开源协议进行发布,永久`100%`开源免费。
# 贡献
感谢所有参与`GoFrame`开发的贡献者。 [[贡献者列表](https://github.com/gogf/gf/graphs/contributors)].
<a href="https://github.com/gogf/gf/graphs/contributors"><img src="https://opencollective.com/goframe/contributors.svg?width=890&button=false" /></a>
# 捐赠
如果您喜欢`GF`,要不[给开发者来杯咖啡吧](DONATOR.MD)
请在捐赠时备注您的`github`/`gitee`账号名称。
# 赞助
赞助支持`GF`框架的快速研发,如果您感兴趣,请联系 微信 `389961817` / 邮件 `john@goframe.org`。
# 感谢
<a href="https://www.jetbrains.com/?from=GoFrame"><img src="https://goframe.org/images/jetbrains.png" width="100" alt="JetBrains"/></a>

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

@ -10,6 +10,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"github.com/gogf/gf/internal/empty"
"github.com/gogf/gf/text/gstr"
"math"
"sort"
@ -176,6 +177,9 @@ func (a *Array) InsertAfter(index int, value interface{}) *Array {
func (a *Array) Remove(index int) interface{} {
a.mu.Lock()
defer a.mu.Unlock()
if index < 0 || index >= len(a.array) {
return nil
}
// Determine array boundaries when deleting to improve deletion efficiency。
if index == 0 {
value := a.array[0]
@ -194,6 +198,16 @@ func (a *Array) Remove(index int) interface{} {
return value
}
// RemoveValue removes an item by value.
// It returns true if value is found in the array, or else false if not found.
func (a *Array) RemoveValue(value interface{}) bool {
if i := a.Search(value); i != -1 {
a.Remove(i)
return true
}
return false
}
// PushLeft pushes one or multiple items to the beginning of array.
func (a *Array) PushLeft(value ...interface{}) *Array {
a.mu.Lock()
@ -223,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))
@ -236,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
@ -246,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
@ -256,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
}
@ -268,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
@ -418,9 +447,6 @@ func (a *Array) Contains(value interface{}) bool {
// Search searches array by <value>, returns the index of <value>,
// or returns -1 if not exists.
func (a *Array) Search(value interface{}) int {
if len(a.array) == 0 {
return -1
}
a.mu.RLock()
result := -1
for index, v := range a.array {
@ -430,7 +456,20 @@ func (a *Array) Search(value interface{}) int {
}
}
a.mu.RUnlock()
return result
}
func (a *Array) doSearch(value interface{}) int {
if len(a.array) == 0 {
return -1
}
result := -1
for index, v := range a.array {
if v == value {
result = index
break
}
}
return result
}
@ -696,3 +735,53 @@ func (a *Array) UnmarshalJSON(b []byte) error {
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for array.
func (a *Array) UnmarshalValue(value interface{}) error {
if a.mu == nil {
a.mu = rwmutex.New()
}
a.mu.Lock()
defer a.mu.Unlock()
switch value.(type) {
case string, []byte:
return json.Unmarshal(gconv.Bytes(value), &a.array)
default:
a.array = gconv.SliceAny(value)
}
return nil
}
// FilterNil removes all nil value of the array.
func (a *Array) FilterNil() *Array {
a.mu.Lock()
defer a.mu.Unlock()
for i := 0; i < len(a.array); {
if empty.IsNil(a.array[i]) {
a.array = append(a.array[:i], a.array[i+1:]...)
} else {
i++
}
}
return a
}
// FilterEmpty removes all empty value of the array.
// Values like: 0, nil, false, "", len(slice/map/chan) == 0 are considered empty.
func (a *Array) FilterEmpty() *Array {
a.mu.Lock()
defer a.mu.Unlock()
for i := 0; i < len(a.array); {
if empty.IsEmpty(a.array[i]) {
a.array = append(a.array[:i], a.array[i+1:]...)
} else {
i++
}
}
return a
}
// IsEmpty checks whether the array is empty.
func (a *Array) IsEmpty() bool {
return a.Len() == 0
}

View File

@ -176,9 +176,13 @@ 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()
if index < 0 || index >= len(a.array) {
return 0
}
// Determine array boundaries when deleting to improve deletion efficiency.
if index == 0 {
value := a.array[0]
@ -197,6 +201,16 @@ func (a *IntArray) Remove(index int) int {
return value
}
// RemoveValue removes an item by value.
// It returns true if value is found in the array, or else false if not found.
func (a *IntArray) RemoveValue(value int) bool {
if i := a.Search(value); i != -1 {
a.Remove(i)
return true
}
return false
}
// PushLeft pushes one or multiple items to the beginning of array.
func (a *IntArray) PushLeft(value ...int) *IntArray {
a.mu.Lock()
@ -215,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)))
}
@ -245,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))
@ -259,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
}
@ -271,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
@ -430,9 +467,6 @@ func (a *IntArray) Contains(value int) bool {
// Search searches array by <value>, returns the index of <value>,
// or returns -1 if not exists.
func (a *IntArray) Search(value int) int {
if len(a.array) == 0 {
return -1
}
a.mu.RLock()
result := -1
for index, v := range a.array {
@ -442,7 +476,6 @@ func (a *IntArray) Search(value int) int {
}
}
a.mu.RUnlock()
return result
}
@ -691,3 +724,38 @@ func (a *IntArray) UnmarshalJSON(b []byte) error {
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for array.
func (a *IntArray) UnmarshalValue(value interface{}) error {
if a.mu == nil {
a.mu = rwmutex.New()
}
a.mu.Lock()
defer a.mu.Unlock()
switch value.(type) {
case string, []byte:
return json.Unmarshal(gconv.Bytes(value), &a.array)
default:
a.array = gconv.SliceInt(value)
}
return nil
}
// FilterEmpty removes all zero value of the array.
func (a *IntArray) FilterEmpty() *IntArray {
a.mu.Lock()
defer a.mu.Unlock()
for i := 0; i < len(a.array); {
if a.array[i] == 0 {
a.array = append(a.array[:i], a.array[i+1:]...)
} else {
i++
}
}
return a
}
// IsEmpty checks whether the array is empty.
func (a *IntArray) IsEmpty() bool {
return a.Len() == 0
}

View File

@ -162,9 +162,13 @@ 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()
if index < 0 || index >= len(a.array) {
return ""
}
// Determine array boundaries when deleting to improve deletion efficiency。
if index == 0 {
value := a.array[0]
@ -183,6 +187,16 @@ func (a *StrArray) Remove(index int) string {
return value
}
// RemoveValue removes an item by value.
// It returns true if value is found in the array, or else false if not found.
func (a *StrArray) RemoveValue(value string) bool {
if i := a.Search(value); i != -1 {
a.Remove(i)
return true
}
return false
}
// PushLeft pushes one or multiple items to the beginning of array.
func (a *StrArray) PushLeft(value ...string) *StrArray {
a.mu.Lock()
@ -201,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)))
}
@ -231,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))
@ -248,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
@ -257,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
@ -687,3 +725,38 @@ func (a *StrArray) UnmarshalJSON(b []byte) error {
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for array.
func (a *StrArray) UnmarshalValue(value interface{}) error {
if a.mu == nil {
a.mu = rwmutex.New()
}
a.mu.Lock()
defer a.mu.Unlock()
switch value.(type) {
case string, []byte:
return json.Unmarshal(gconv.Bytes(value), &a.array)
default:
a.array = gconv.SliceStr(value)
}
return nil
}
// FilterEmpty removes all empty string value of the array.
func (a *StrArray) FilterEmpty() *StrArray {
a.mu.Lock()
defer a.mu.Unlock()
for i := 0; i < len(a.array); {
if a.array[i] == "" {
a.array = append(a.array[:i], a.array[i+1:]...)
} else {
i++
}
}
return a
}
// IsEmpty checks whether the array is empty.
func (a *StrArray) IsEmpty() bool {
return a.Len() == 0
}

View File

@ -10,6 +10,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"github.com/gogf/gf/internal/empty"
"github.com/gogf/gf/text/gstr"
"github.com/gogf/gf/util/gutil"
"math"
@ -32,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...)
}
@ -160,6 +161,9 @@ func (a *SortedArray) Get(index int) interface{} {
func (a *SortedArray) Remove(index int) interface{} {
a.mu.Lock()
defer a.mu.Unlock()
if index < 0 || index >= len(a.array) {
return nil
}
// Determine array boundaries when deleting to improve deletion efficiency.
if index == 0 {
value := a.array[0]
@ -178,10 +182,23 @@ func (a *SortedArray) Remove(index int) interface{} {
return value
}
// RemoveValue removes an item by value.
// It returns true if value is found in the array, or else false if not found.
func (a *SortedArray) RemoveValue(value interface{}) bool {
if i := a.Search(value); i != -1 {
a.Remove(i)
return true
}
return false
}
// PopLeft pops and returns an item from the beginning of array.
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
@ -192,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
@ -209,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))
@ -226,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
@ -235,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
@ -425,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 {
@ -642,10 +674,82 @@ func (a *SortedArray) UnmarshalJSON(b []byte) error {
if err := json.Unmarshal(b, &a.array); err != nil {
return err
}
if a.comparator != nil {
if a.comparator != nil && a.array != nil {
sort.Slice(a.array, func(i, j int) bool {
return a.comparator(a.array[i], a.array[j]) < 0
})
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for array.
func (a *SortedArray) UnmarshalValue(value interface{}) (err error) {
if a.mu == nil {
a.mu = rwmutex.New()
a.unique = gtype.NewBool()
// Note that the comparator is string comparator in default.
a.comparator = gutil.ComparatorString
}
a.mu.Lock()
defer a.mu.Unlock()
switch value.(type) {
case string, []byte:
err = json.Unmarshal(gconv.Bytes(value), &a.array)
default:
a.array = gconv.SliceAny(value)
}
if a.comparator != nil && a.array != nil {
sort.Slice(a.array, func(i, j int) bool {
return a.comparator(a.array[i], a.array[j]) < 0
})
}
return err
}
// FilterNil removes all nil value of the array.
func (a *SortedArray) FilterNil() *SortedArray {
a.mu.Lock()
defer a.mu.Unlock()
for i := 0; i < len(a.array); {
if empty.IsNil(a.array[i]) {
a.array = append(a.array[:i], a.array[i+1:]...)
} else {
break
}
}
for i := len(a.array) - 1; i >= 0; {
if empty.IsNil(a.array[i]) {
a.array = append(a.array[:i], a.array[i+1:]...)
} else {
break
}
}
return a
}
// FilterEmpty removes all empty value of the array.
// Values like: 0, nil, false, "", len(slice/map/chan) == 0 are considered empty.
func (a *SortedArray) FilterEmpty() *SortedArray {
a.mu.Lock()
defer a.mu.Unlock()
for i := 0; i < len(a.array); {
if empty.IsEmpty(a.array[i]) {
a.array = append(a.array[:i], a.array[i+1:]...)
} else {
break
}
}
for i := len(a.array) - 1; i >= 0; {
if empty.IsEmpty(a.array[i]) {
a.array = append(a.array[:i], a.array[i+1:]...)
} else {
break
}
}
return a
}
// IsEmpty checks whether the array is empty.
func (a *SortedArray) IsEmpty() bool {
return a.Len() == 0
}

View File

@ -143,9 +143,13 @@ 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()
if index < 0 || index >= len(a.array) {
return 0
}
// Determine array boundaries when deleting to improve deletion efficiency.
if index == 0 {
value := a.array[0]
@ -164,26 +168,51 @@ func (a *SortedIntArray) Remove(index int) int {
return value
}
// RemoveValue removes an item by value.
// It returns true if value is found in the array, or else false if not found.
func (a *SortedIntArray) RemoveValue(value int) bool {
if i := a.Search(value); i != -1 {
a.Remove(i)
return true
}
return false
}
// 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)))
}
@ -195,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))
@ -212,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
@ -221,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
@ -416,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 {
@ -427,7 +469,6 @@ func (a *SortedIntArray) Unique() *SortedIntArray {
i++
}
}
a.mu.Unlock()
return a
}
@ -616,6 +657,56 @@ func (a *SortedIntArray) UnmarshalJSON(b []byte) error {
if err := json.Unmarshal(b, &a.array); err != nil {
return err
}
sort.Ints(a.array)
if a.array != nil {
sort.Ints(a.array)
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for array.
func (a *SortedIntArray) UnmarshalValue(value interface{}) (err error) {
if a.mu == nil {
a.mu = rwmutex.New()
a.unique = gtype.NewBool()
// Note that the comparator is string comparator in default.
a.comparator = defaultComparatorInt
}
a.mu.Lock()
defer a.mu.Unlock()
switch value.(type) {
case string, []byte:
err = json.Unmarshal(gconv.Bytes(value), &a.array)
default:
a.array = gconv.SliceInt(value)
}
if a.array != nil {
sort.Ints(a.array)
}
return err
}
// FilterEmpty removes all zero value of the array.
func (a *SortedIntArray) FilterEmpty() *SortedIntArray {
a.mu.Lock()
defer a.mu.Unlock()
for i := 0; i < len(a.array); {
if a.array[i] == 0 {
a.array = append(a.array[:i], a.array[i+1:]...)
} else {
break
}
}
for i := len(a.array) - 1; i >= 0; {
if a.array[i] == 0 {
a.array = append(a.array[:i], a.array[i+1:]...)
} else {
break
}
}
return a
}
// IsEmpty checks whether the array is empty.
func (a *SortedIntArray) IsEmpty() bool {
return a.Len() == 0
}

View File

@ -128,9 +128,13 @@ 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()
if index < 0 || index >= len(a.array) {
return ""
}
// Determine array boundaries when deleting to improve deletion efficiency.
if index == 0 {
value := a.array[0]
@ -149,26 +153,51 @@ func (a *SortedStrArray) Remove(index int) string {
return value
}
// RemoveValue removes an item by value.
// It returns true if value is found in the array, or else false if not found.
func (a *SortedStrArray) RemoveValue(value string) bool {
if i := a.Search(value); i != -1 {
a.Remove(i)
return true
}
return false
}
// 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)))
}
@ -180,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))
@ -197,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
@ -206,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
@ -401,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 {
@ -412,7 +454,6 @@ func (a *SortedStrArray) Unique() *SortedStrArray {
i++
}
}
a.mu.Unlock()
return a
}
@ -612,6 +653,56 @@ func (a *SortedStrArray) UnmarshalJSON(b []byte) error {
if err := json.Unmarshal(b, &a.array); err != nil {
return err
}
sort.Strings(a.array)
if a.array != nil {
sort.Strings(a.array)
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for array.
func (a *SortedStrArray) UnmarshalValue(value interface{}) (err error) {
if a.mu == nil {
a.mu = rwmutex.New()
a.unique = gtype.NewBool()
// Note that the comparator is string comparator in default.
a.comparator = defaultComparatorStr
}
a.mu.Lock()
defer a.mu.Unlock()
switch value.(type) {
case string, []byte:
err = json.Unmarshal(gconv.Bytes(value), &a.array)
default:
a.array = gconv.SliceStr(value)
}
if a.array != nil {
sort.Strings(a.array)
}
return err
}
// FilterEmpty removes all empty string value of the array.
func (a *SortedStrArray) FilterEmpty() *SortedStrArray {
a.mu.Lock()
defer a.mu.Unlock()
for i := 0; i < len(a.array); {
if a.array[i] == "" {
a.array = append(a.array[:i], a.array[i+1:]...)
} else {
break
}
}
for i := len(a.array) - 1; i >= 0; {
if a.array[i] == "" {
a.array = append(a.array[:i], a.array[i+1:]...)
} else {
break
}
}
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,39 +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)
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()
@ -62,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
@ -145,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"}
@ -157,157 +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.C(t, func(t *gtest.T) {
a1 := []interface{}{1, 2, 3, 4, 5}
array1 := garray.NewArrayFrom(a1)
chunks := array1.Chunk(3)
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.C(t, func(t *gtest.T) {
a1 := []interface{}{1, 2, 3, 4, 5, 6}
array1 := garray.NewArrayFrom(a1)
chunks := array1.Chunk(2)
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.C(t, func(t *gtest.T) {
a1 := []interface{}{1, 2, 3, 4, 5, 6}
array1 := garray.NewArrayFrom(a1)
chunks := array1.Chunk(3)
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"}
@ -316,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)
@ -374,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)
@ -406,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
@ -441,59 +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.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 V struct {
Name string
Array *garray.Array
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": []byte(`[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.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": 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.C(t, func(t *gtest.T) {
values := g.Slice{0, 1, 2, 3, 4, "", g.Slice{}}
array := garray.NewArrayFromCopy(values)
t.Assert(array.FilterNil().Slice(), values)
})
gtest.C(t, func(t *gtest.T) {
array := garray.NewArrayFromCopy(g.Slice{nil, 1, 2, 3, 4, nil})
t.Assert(array.FilterNil(), g.Slice{1, 2, 3, 4})
})
}
func TestArray_FilterEmpty(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := garray.NewArrayFrom(g.Slice{0, 1, 2, 3, 4, "", g.Slice{}})
t.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4})
})
gtest.C(t, func(t *gtest.T) {
array := garray.NewArrayFrom(g.Slice{1, 2, 3, 4})
t.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4})
})
}

View File

@ -21,35 +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.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()
@ -59,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
@ -145,232 +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.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5}
array1 := garray.NewIntArrayFrom(a1)
chunks := array1.Chunk(3)
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.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5, 6}
array1 := garray.NewIntArrayFrom(a1)
chunks := array1.Chunk(2)
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.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5, 6}
array1 := garray.NewIntArrayFrom(a1)
chunks := array1.Chunk(3)
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)
@ -396,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)
@ -441,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
@ -475,59 +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.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 V struct {
Name string
Array *garray.IntArray
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": []byte(`[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.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": 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.C(t, func(t *gtest.T) {
array := garray.NewIntArrayFrom(g.SliceInt{0, 1, 2, 3, 4, 0})
t.Assert(array.FilterEmpty(), g.SliceInt{1, 2, 3, 4})
})
gtest.C(t, func(t *gtest.T) {
array := garray.NewIntArrayFrom(g.SliceInt{1, 2, 3, 4})
t.Assert(array.FilterEmpty(), g.SliceInt{1, 2, 3, 4})
})
}

View File

@ -21,36 +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.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()
@ -58,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) {
@ -143,239 +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.C(t, func(t *gtest.T) {
a1 := []string{"1", "2", "3", "4", "5"}
array1 := garray.NewStrArrayFrom(a1)
chunks := array1.Chunk(3)
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.C(t, func(t *gtest.T) {
a1 := []string{"1", "2", "3", "4", "5", "6"}
array1 := garray.NewStrArrayFrom(a1)
chunks := array1.Chunk(2)
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.C(t, func(t *gtest.T) {
a1 := []string{"1", "2", "3", "4", "5", "6"}
array1 := garray.NewStrArrayFrom(a1)
chunks := array1.Chunk(3)
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)
@ -401,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)
@ -445,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
@ -479,59 +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.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 V struct {
Name string
Array *garray.StrArray
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": []byte(`["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.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": 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.C(t, func(t *gtest.T) {
array := garray.NewStrArrayFrom(g.SliceStr{"", "1", "2", "0"})
t.Assert(array.FilterEmpty(), g.SliceStr{"1", "2", "0"})
})
gtest.C(t, func(t *gtest.T) {
array := garray.NewStrArrayFrom(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,168 +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)
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))
@ -241,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"}
@ -269,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 {
@ -285,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 {
@ -316,17 +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.C(t, func(t *gtest.T) {
a1 := []interface{}{1, 2, 3, 4, 5}
array1 := garray.NewSortedArrayFrom(a1, gutil.ComparatorInt)
chunks := array1.Chunk(3)
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.C(t, func(t *gtest.T) {
a1 := []interface{}{1, 2, 3, 4, 5, 6}
array1 := garray.NewSortedArrayFrom(a1, gutil.ComparatorInt)
chunks := array1.Chunk(2)
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.C(t, func(t *gtest.T) {
a1 := []interface{}{1, 2, 3, 4, 5, 6}
array1 := garray.NewSortedArrayFrom(a1, gutil.ComparatorInt)
chunks := array1.Chunk(3)
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 {
@ -335,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 {
@ -364,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 {
@ -378,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 {
@ -422,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 {
@ -438,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))
}
@ -473,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))
}
@ -508,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
@ -533,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
@ -574,63 +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.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 V struct {
Name string
Array *garray.SortedArray
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": []byte(`[2,3,1]`),
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Array.Slice(), g.Slice{1, 2, 3})
})
// Map
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": g.Slice{2, 3, 1},
}, &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.C(t, func(t *gtest.T) {
values := g.Slice{0, 1, 2, 3, 4, "", g.Slice{}}
array := garray.NewSortedArrayFromCopy(values, gutil.ComparatorInt)
t.Assert(array.FilterNil().Slice(), g.Slice{0, "", g.Slice{}, 1, 2, 3, 4})
})
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedArrayFromCopy(g.Slice{nil, 1, 2, 3, 4, nil}, gutil.ComparatorInt)
t.Assert(array.FilterNil(), g.Slice{1, 2, 3, 4})
})
}
func TestSortedArray_FilterEmpty(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedArrayFrom(g.Slice{0, 1, 2, 3, 4, "", g.Slice{}}, gutil.ComparatorInt)
t.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4})
})
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedArrayFrom(g.Slice{1, 2, 3, 4}, gutil.ComparatorInt)
t.Assert(array.FilterEmpty(), g.Slice{1, 2, 3, 4})
})
}

View File

@ -21,323 +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)
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.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5}
array1 := garray.NewSortedIntArrayFrom(a1)
chunks := array1.Chunk(3)
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.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5, 6}
array1 := garray.NewSortedIntArrayFrom(a1)
chunks := array1.Chunk(2)
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.C(t, func(t *gtest.T) {
a1 := []int{1, 2, 3, 4, 5, 6}
array1 := garray.NewSortedIntArrayFrom(a1)
chunks := array1.Chunk(3)
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)
@ -362,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)
@ -394,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
@ -417,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
@ -457,59 +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.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 V struct {
Name string
Array *garray.SortedIntArray
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": []byte(`[2,3,1]`),
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Array.Slice(), g.Slice{1, 2, 3})
})
// Map
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": g.Slice{2, 3, 1},
}, &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.C(t, func(t *gtest.T) {
array := garray.NewSortedIntArrayFrom(g.SliceInt{0, 1, 2, 3, 4, 0})
t.Assert(array.FilterEmpty(), g.SliceInt{1, 2, 3, 4})
})
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedIntArrayFrom(g.SliceInt{1, 2, 3, 4})
t.Assert(array.FilterEmpty(), g.SliceInt{1, 2, 3, 4})
})
}

View File

@ -20,330 +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(2), "c")
gtest.Assert(array1.Get(2), "d")
gtest.Assert(array1.Len(), 3)
gtest.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(-1), "")
t.Assert(array1.Remove(100000), "")
t.Assert(array1.Remove(2), "c")
t.Assert(array1.Get(2), "d")
t.Assert(array1.Len(), 3)
t.Assert(array1.Contains("c"), 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.C(t, func(t *gtest.T) {
a1 := []string{"1", "2", "3", "4", "5"}
array1 := garray.NewSortedStrArrayFrom(a1)
chunks := array1.Chunk(3)
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.C(t, func(t *gtest.T) {
a1 := []string{"1", "2", "3", "4", "5", "6"}
array1 := garray.NewSortedStrArrayFrom(a1)
chunks := array1.Chunk(2)
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.C(t, func(t *gtest.T) {
a1 := []string{"1", "2", "3", "4", "5", "6"}
array1 := garray.NewSortedStrArrayFrom(a1)
chunks := array1.Chunk(3)
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)
@ -369,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)
@ -401,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
@ -425,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
@ -467,59 +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.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 V struct {
Name string
Array *garray.SortedStrArray
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": []byte(`["1","3","2"]`),
}, &v)
t.Assert(err, nil)
t.Assert(v.Name, "john")
t.Assert(v.Array.Slice(), g.SliceStr{"1", "2", "3"})
})
// Map
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"array": g.SliceStr{"1", "3", "2"},
}, &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.C(t, func(t *gtest.T) {
array := garray.NewSortedStrArrayFrom(g.SliceStr{"", "1", "2", "0"})
t.Assert(array.FilterEmpty(), g.SliceStr{"0", "1", "2"})
})
gtest.C(t, func(t *gtest.T) {
array := garray.NewSortedStrArrayFrom(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

@ -438,3 +438,22 @@ func (l *List) UnmarshalJSON(b []byte) error {
l.PushBacks(array)
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for list.
func (l *List) UnmarshalValue(value interface{}) (err error) {
if l.mu == nil {
l.mu = rwmutex.New()
l.list = list.New()
}
l.mu.Lock()
defer l.mu.Unlock()
var array []interface{}
switch value.(type) {
case string, []byte:
err = json.Unmarshal(gconv.Bytes(value), &array)
default:
array = gconv.SliceAny(value)
}
l.PushBacks(array)
return err
}

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,346 +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 TList struct {
Name string
List *List
}
// JSON
gtest.C(t, func(t *gtest.T) {
var tlist *TList
err := gconv.Struct(map[string]interface{}{
"name": "john",
"list": []byte(`[1,2,3]`),
}, &tlist)
t.Assert(err, nil)
t.Assert(tlist.Name, "john")
t.Assert(tlist.List.FrontAll(), []interface{}{1, 2, 3})
})
// Map
gtest.C(t, func(t *gtest.T) {
var tlist *TList
err := gconv.Struct(map[string]interface{}{
"name": "john",
"list": []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

@ -436,3 +436,17 @@ func (m *AnyAnyMap) UnmarshalJSON(b []byte) error {
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for map.
func (m *AnyAnyMap) UnmarshalValue(value interface{}) (err error) {
if m.mu == nil {
m.mu = rwmutex.New()
m.data = make(map[interface{}]interface{})
}
m.mu.Lock()
defer m.mu.Unlock()
for k, v := range gconv.Map(value) {
m.data[k] = v
}
return
}

View File

@ -432,3 +432,22 @@ func (m *IntAnyMap) UnmarshalJSON(b []byte) error {
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for map.
func (m *IntAnyMap) UnmarshalValue(value interface{}) (err error) {
if m.mu == nil {
m.mu = rwmutex.New()
m.data = make(map[int]interface{})
}
m.mu.Lock()
defer m.mu.Unlock()
switch value.(type) {
case string, []byte:
return json.Unmarshal(gconv.Bytes(value), &m.data)
default:
for k, v := range gconv.Map(value) {
m.data[gconv.Int(k)] = v
}
}
return
}

View File

@ -409,3 +409,22 @@ func (m *IntIntMap) UnmarshalJSON(b []byte) error {
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for map.
func (m *IntIntMap) UnmarshalValue(value interface{}) (err error) {
if m.mu == nil {
m.mu = rwmutex.New()
m.data = make(map[int]int)
}
m.mu.Lock()
defer m.mu.Unlock()
switch value.(type) {
case string, []byte:
return json.Unmarshal(gconv.Bytes(value), &m.data)
default:
for k, v := range gconv.Map(value) {
m.data[gconv.Int(k)] = gconv.Int(v)
}
}
return
}

View File

@ -410,3 +410,22 @@ func (m *IntStrMap) UnmarshalJSON(b []byte) error {
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for map.
func (m *IntStrMap) UnmarshalValue(value interface{}) (err error) {
if m.mu == nil {
m.mu = rwmutex.New()
m.data = make(map[int]string)
}
m.mu.Lock()
defer m.mu.Unlock()
switch value.(type) {
case string, []byte:
return json.Unmarshal(gconv.Bytes(value), &m.data)
default:
for k, v := range gconv.Map(value) {
m.data[gconv.Int(k)] = gconv.String(v)
}
}
return
}

View File

@ -428,3 +428,15 @@ func (m *StrAnyMap) UnmarshalJSON(b []byte) error {
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for map.
func (m *StrAnyMap) UnmarshalValue(value interface{}) (err error) {
if m.mu == nil {
m.mu = rwmutex.New()
m.data = make(map[string]interface{})
}
m.mu.Lock()
defer m.mu.Unlock()
m.data = gconv.Map(value)
return
}

View File

@ -411,3 +411,22 @@ func (m *StrIntMap) UnmarshalJSON(b []byte) error {
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for map.
func (m *StrIntMap) UnmarshalValue(value interface{}) (err error) {
if m.mu == nil {
m.mu = rwmutex.New()
m.data = make(map[string]int)
}
m.mu.Lock()
defer m.mu.Unlock()
switch value.(type) {
case string, []byte:
return json.Unmarshal(gconv.Bytes(value), &m.data)
default:
for k, v := range gconv.Map(value) {
m.data[k] = gconv.Int(v)
}
}
return
}

View File

@ -9,6 +9,7 @@ package gmap
import (
"encoding/json"
"github.com/gogf/gf/util/gconv"
"github.com/gogf/gf/internal/empty"
@ -412,3 +413,14 @@ func (m *StrStrMap) UnmarshalJSON(b []byte) error {
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for map.
func (m *StrStrMap) UnmarshalValue(value interface{}) (err error) {
if m.mu == nil {
m.mu = rwmutex.New()
}
m.mu.Lock()
defer m.mu.Unlock()
m.data = gconv.MapStrStr(value)
return
}

View File

@ -491,3 +491,22 @@ func (m *ListMap) UnmarshalJSON(b []byte) error {
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for map.
func (m *ListMap) UnmarshalValue(value interface{}) (err error) {
if m.mu == nil {
m.mu = rwmutex.New()
m.data = make(map[interface{}]*glist.Element)
m.list = glist.New()
}
m.mu.Lock()
defer m.mu.Unlock()
for k, v := range gconv.Map(value) {
if e, ok := m.data[k]; !ok {
m.data[k] = m.list.PushBack(&gListMapNode{k, v})
} else {
e.Value = &gListMapNode{k, v}
}
}
return
}

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,89 +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 V struct {
Name string
Map *gmap.Map
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"k1":"v1","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.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.Map{
"k1": "v1",
"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

@ -10,6 +10,7 @@ import (
"encoding/json"
"github.com/gogf/gf/container/garray"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/util/gconv"
"testing"
"github.com/gogf/gf/container/gmap"
@ -23,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",
@ -185,75 +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 V struct {
Name string
Map *gmap.IntAnyMap
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"1":"v1","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.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.MapIntAny{
1: "v1",
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

@ -10,6 +10,7 @@ import (
"encoding/json"
"github.com/gogf/gf/container/garray"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/util/gconv"
"testing"
"github.com/gogf/gf/container/gmap"
@ -23,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,
@ -188,75 +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 V struct {
Name string
Map *gmap.IntIntMap
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"1":1,"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.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.MapIntAny{
1: 1,
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

@ -10,6 +10,7 @@ import (
"encoding/json"
"github.com/gogf/gf/container/garray"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/util/gconv"
"testing"
"github.com/gogf/gf/container/gmap"
@ -23,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",
@ -189,75 +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 V struct {
Name string
Map *gmap.IntStrMap
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"1":"v1","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.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.MapIntAny{
1: "v1",
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,90 +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 V struct {
Name string
Map *gmap.ListMap
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"1":"v1","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.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.MapIntAny{
1: "v1",
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

@ -10,6 +10,7 @@ import (
"encoding/json"
"github.com/gogf/gf/container/garray"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/util/gconv"
"testing"
"github.com/gogf/gf/container/gmap"
@ -20,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",
@ -183,89 +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 V struct {
Name string
Map *gmap.StrAnyMap
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"k1":"v1","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.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.Map{
"k1": "v1",
"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

@ -10,6 +10,7 @@ import (
"encoding/json"
"github.com/gogf/gf/container/garray"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/util/gconv"
"testing"
"github.com/gogf/gf/container/gmap"
@ -20,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,
@ -186,89 +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 V struct {
Name string
Map *gmap.StrIntMap
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"k1":1,"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.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.Map{
"k1": 1,
"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

@ -10,6 +10,7 @@ import (
"encoding/json"
"github.com/gogf/gf/container/garray"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/util/gconv"
"testing"
"github.com/gogf/gf/container/gmap"
@ -20,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",
@ -183,89 +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 V struct {
Name string
Map *gmap.StrStrMap
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"k1":"v1","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.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.Map{
"k1": "v1",
"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,36 +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 V struct {
Name string
Map *gmap.TreeMap
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": []byte(`{"k1":"v1","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.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(map[string]interface{}{
"name": "john",
"map": g.Map{
"k1": "v1",
"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,52 +50,69 @@ 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.Millisecond() + 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 {
f := r.(*poolItem)
if f.expire == 0 || f.expire > gtime.Millisecond() {
if f.expire == 0 || f.expire > gtime.TimestampMilli() {
return f.value, nil
}
} else {
@ -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.Millisecond() {
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) {
@ -36,7 +37,7 @@ func BenchmarkSyncPoolPut(b *testing.B) {
}
}
func BenchmarkGpoolGet(b *testing.B) {
func BenchmarkSyncPoolGet(b *testing.B) {
for i := 0; i < b.N; i++ {
syncp.Get()
}

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

@ -430,3 +430,24 @@ func (set *Set) UnmarshalJSON(b []byte) error {
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for set.
func (set *Set) UnmarshalValue(value interface{}) (err error) {
if set.mu == nil {
set.mu = rwmutex.New()
set.data = make(map[interface{}]struct{})
}
set.mu.Lock()
defer set.mu.Unlock()
var array []interface{}
switch value.(type) {
case string, []byte:
err = json.Unmarshal(gconv.Bytes(value), &array)
default:
array = gconv.SliceAny(value)
}
for _, v := range array {
set.data[v] = struct{}{}
}
return
}

View File

@ -401,3 +401,24 @@ func (set *IntSet) UnmarshalJSON(b []byte) error {
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for set.
func (set *IntSet) UnmarshalValue(value interface{}) (err error) {
if set.mu == nil {
set.mu = rwmutex.New()
set.data = make(map[int]struct{})
}
set.mu.Lock()
defer set.mu.Unlock()
var array []int
switch value.(type) {
case string, []byte:
err = json.Unmarshal(gconv.Bytes(value), &array)
default:
array = gconv.SliceInt(value)
}
for _, v := range array {
set.data[v] = struct{}{}
}
return
}

View File

@ -417,3 +417,24 @@ func (set *StrSet) UnmarshalJSON(b []byte) error {
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for set.
func (set *StrSet) UnmarshalValue(value interface{}) (err error) {
if set.mu == nil {
set.mu = rwmutex.New()
set.data = make(map[string]struct{})
}
set.mu.Lock()
defer set.mu.Unlock()
var array []string
switch value.(type) {
case string, []byte:
err = json.Unmarshal(gconv.Bytes(value), &array)
default:
array = gconv.SliceStr(value)
}
for _, v := range array {
set.data[v] = struct{}{}
}
return
}

View File

@ -10,6 +10,8 @@ package gset_test
import (
"encoding/json"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/util/gconv"
"strings"
"github.com/gogf/gf/container/garray"
@ -20,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)
@ -75,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{}{},
})
@ -99,265 +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 V struct {
Name string
Set *gset.Set
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"set": []byte(`["k1","k2","k3"]`),
}, &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.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"set": g.Slice{"k1", "k2", "k3"},
}, &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

@ -10,6 +10,8 @@ package gset_test
import (
"encoding/json"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/util/gconv"
"strings"
"testing"
@ -19,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)
@ -54,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{}{},
})
@ -78,249 +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 V struct {
Name string
Set *gset.IntSet
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"set": []byte(`[1,2,3]`),
}, &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.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"set": g.Slice{1, 2, 3},
}, &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

@ -10,6 +10,8 @@ package gset_test
import (
"encoding/json"
"github.com/gogf/gf/frame/g"
"github.com/gogf/gf/util/gconv"
"strings"
"testing"
@ -19,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)
@ -54,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{}{},
})
@ -78,285 +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 V struct {
Name string
Set *gset.StrSet
}
// JSON
gtest.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"set": []byte(`["1","2","3"]`),
}, &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.C(t, func(t *gtest.T) {
var v *V
err := gconv.Struct(g.Map{
"name": "john",
"set": g.SliceStr{"1", "2", "3"},
}, &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

@ -942,3 +942,17 @@ func (tree *RedBlackTree) UnmarshalJSON(b []byte) error {
}
return nil
}
// UnmarshalValue is an interface implement which sets any type of value for map.
func (tree *RedBlackTree) UnmarshalValue(value interface{}) (err error) {
if tree.mu == nil {
tree.mu = rwmutex.New()
tree.comparator = gutil.ComparatorString
}
tree.mu.Lock()
defer tree.mu.Unlock()
for k, v := range gconv.Map(value) {
tree.doSet(k, v)
}
return
}

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)
}
})
}

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