mirror of
https://gitee.com/johng/gf
synced 2026-06-07 02:12:11 +08:00
21
.travis.yml
21
.travis.yml
@ -1,7 +1,6 @@
|
||||
language: go
|
||||
|
||||
go:
|
||||
- "1.10.x"
|
||||
- "1.11.x"
|
||||
- "1.12.x"
|
||||
|
||||
@ -11,29 +10,29 @@ branches:
|
||||
- develop
|
||||
|
||||
env:
|
||||
- GO111MODULE=on
|
||||
- GO111MODULE=on
|
||||
|
||||
services:
|
||||
- mysql
|
||||
- redis-server
|
||||
- mysql
|
||||
- redis-server
|
||||
|
||||
addons:
|
||||
hosts:
|
||||
- local
|
||||
- local
|
||||
|
||||
before_install:
|
||||
- pwd
|
||||
- pwd
|
||||
|
||||
install:
|
||||
- cat /etc/hosts
|
||||
- cat /etc/hosts
|
||||
|
||||
script:
|
||||
- cd g
|
||||
- GOARCH=386 go test -v ./...
|
||||
- GOARCH=amd64 go test -v ./... -race -coverprofile=coverage.txt -covermode=atomic
|
||||
- cd g
|
||||
- GOARCH=386 go test -v ./...
|
||||
- GOARCH=amd64 go test -v ./... -race -coverprofile=coverage.txt -covermode=atomic
|
||||
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
|
||||
|
||||
|
||||
@ -64,13 +64,15 @@ func main() {
|
||||
|
||||
`GF` is licensed under the [MIT License](LICENSE), 100% free and open-source, forever.
|
||||
|
||||
|
||||
# Contributors
|
||||
|
||||
- [aloncn](https://github.com/aloncn)
|
||||
- [chenyang351](https://github.com/chenyang351)
|
||||
- [garfieldkwong](https://gitee.com/garfieldkwong)
|
||||
- [hailaz](https://gitee.com/hailaz)
|
||||
- [johng](https://gitee.com/johng)
|
||||
- [johng](https://johng.cn)
|
||||
- [jroam](https://github.com/jroam)
|
||||
- [pibigstar](https://github.com/pibigstar)
|
||||
- [qq1054000800](https://gitee.com/qq1054000800)
|
||||
- [qq976739120](https://github.com/qq976739120)
|
||||
@ -86,6 +88,7 @@ func main() {
|
||||
|
||||
- [flyke-xu](https://gitee.com/flyke-xu)
|
||||
- [hailaz](https://gitee.com/hailaz)
|
||||
- [ireadx](https://github.com/ireadx)
|
||||
- [mg91](https://gitee.com/mg91)
|
||||
- [pibigstar](https://github.com/pibigstar)
|
||||
- [tiangenglan](https://gitee.com/tiangenglan)
|
||||
@ -98,4 +101,3 @@ func main() {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -30,7 +30,6 @@ go get -u github.com/gogf/gf
|
||||
```
|
||||
require github.com/gogf/gf latest
|
||||
```
|
||||
> 如果您是从旧版本`1.x`升级到`1.5.0`那么请参考:[1.x升级到1.5.0](https://goframe.org/upgradeto150)
|
||||
|
||||
# 限制
|
||||
```shell
|
||||
@ -90,7 +89,8 @@ func main() {
|
||||
- [chenyang351](https://github.com/chenyang351)
|
||||
- [garfieldkwong](https://gitee.com/garfieldkwong)
|
||||
- [hailaz](https://gitee.com/hailaz)
|
||||
- [johng](https://gitee.com/johng)
|
||||
- [johng](https://johng.cn)
|
||||
- [jroam](https://github.com/jroam)
|
||||
- [pibigstar](https://github.com/pibigstar)
|
||||
- [qq1054000800](https://gitee.com/qq1054000800)
|
||||
- [qq976739120](https://github.com/qq976739120)
|
||||
@ -106,6 +106,7 @@ func main() {
|
||||
|
||||
- [flyke-xu](https://gitee.com/flyke-xu)
|
||||
- [hailaz](https://gitee.com/hailaz)
|
||||
- [ireadx](https://github.com/ireadx)
|
||||
- [mg91](https://gitee.com/mg91)
|
||||
- [pibigstar](https://github.com/pibigstar)
|
||||
- [tiangenglan](https://gitee.com/tiangenglan)
|
||||
|
||||
1
TODO.MD
1
TODO.MD
@ -44,6 +44,7 @@
|
||||
1. 添加sqlite数据库的单元测试用例;
|
||||
1. gredis增加cluster支持;
|
||||
1. gset.Add/Remove/Contains方法增加批量操作支持;
|
||||
1. gmlock增加手动清理机制:当内存锁不再使用时,由调用端决定是否清理内存锁;
|
||||
|
||||
# DONE
|
||||
1. gconv完善针对不同类型的判断,例如:尽量减少sprintf("%v", xxx)来执行string类型的转换;
|
||||
|
||||
@ -11,35 +11,39 @@ import (
|
||||
)
|
||||
|
||||
type Bool struct {
|
||||
val int32
|
||||
value int32
|
||||
}
|
||||
|
||||
// NewBool returns a concurrent-safe object for bool type,
|
||||
// with given initial value <value>.
|
||||
func NewBool(value...bool) *Bool {
|
||||
t := &Bool{}
|
||||
if len(value) > 0 {
|
||||
if value[0] {
|
||||
t.val = 1
|
||||
t.value = 1
|
||||
} else {
|
||||
t.val = 0
|
||||
t.value = 0
|
||||
}
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// Clone clones and returns a new concurrent-safe object for bool type.
|
||||
func (t *Bool) Clone() *Bool {
|
||||
return NewBool(t.Val())
|
||||
}
|
||||
|
||||
// 并发安全设置变量值,返回之前的旧值
|
||||
// Set atomically stores value into t.valueue and returns the previous t.value value.
|
||||
func (t *Bool) Set(value bool) (old bool) {
|
||||
if value {
|
||||
old = atomic.SwapInt32(&t.val, 1) == 1
|
||||
old = atomic.SwapInt32(&t.value, 1) == 1
|
||||
} else {
|
||||
old = atomic.SwapInt32(&t.val, 0) == 1
|
||||
old = atomic.SwapInt32(&t.value, 0) == 1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Val atomically loads t.valueue.
|
||||
func (t *Bool) Val() bool {
|
||||
return atomic.LoadInt32(&t.val) > 0
|
||||
return atomic.LoadInt32(&t.value) > 0
|
||||
}
|
||||
|
||||
@ -11,29 +11,36 @@ import (
|
||||
)
|
||||
|
||||
type Byte struct {
|
||||
val int32
|
||||
value int32
|
||||
}
|
||||
|
||||
// NewByte returns a concurrent-safe object for byte type,
|
||||
// with given initial value <value>.
|
||||
func NewByte(value...byte) *Byte {
|
||||
if len(value) > 0 {
|
||||
return &Byte{val : int32(value[0])}
|
||||
return &Byte{
|
||||
value : int32(value[0]),
|
||||
}
|
||||
}
|
||||
return &Byte{}
|
||||
}
|
||||
|
||||
// Clone clones and returns a new concurrent-safe object for byte type.
|
||||
func (t *Byte) Clone() *Byte {
|
||||
return NewByte(t.Val())
|
||||
}
|
||||
|
||||
// 并发安全设置变量值,返回之前的旧值
|
||||
// Set atomically stores value into t.value and returns the previous t.value value.
|
||||
func (t *Byte) Set(value byte) (old byte) {
|
||||
return byte(atomic.SwapInt32(&t.val, int32(value)))
|
||||
return byte(atomic.SwapInt32(&t.value, int32(value)))
|
||||
}
|
||||
|
||||
// Val atomically loads t.value.
|
||||
func (t *Byte) Val() byte {
|
||||
return byte(atomic.LoadInt32(&t.val))
|
||||
return byte(atomic.LoadInt32(&t.value))
|
||||
}
|
||||
|
||||
func (t *Byte) Add(delta int) byte {
|
||||
return byte(atomic.AddInt32(&t.val, int32(delta)))
|
||||
// Add atomically adds delta to t.value and returns the new value.
|
||||
func (t *Byte) Add(delta int) (new byte) {
|
||||
return byte(atomic.AddInt32(&t.value, int32(delta)))
|
||||
}
|
||||
|
||||
@ -9,29 +9,35 @@ package gtype
|
||||
import "sync/atomic"
|
||||
|
||||
type Bytes struct {
|
||||
val atomic.Value
|
||||
value atomic.Value
|
||||
}
|
||||
|
||||
// NewBytes returns a concurrent-safe object for []byte type,
|
||||
// with given initial value <value>.
|
||||
func NewBytes(value...[]byte) *Bytes {
|
||||
t := &Bytes{}
|
||||
if len(value) > 0 {
|
||||
t.val.Store(value[0])
|
||||
t.value.Store(value[0])
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// Clone clones and returns a new concurrent-safe object for []byte type.
|
||||
func (t *Bytes) Clone() *Bytes {
|
||||
return NewBytes(t.Val())
|
||||
}
|
||||
|
||||
// Set atomically stores value into t.value and returns the previous t.value value.
|
||||
// Note: The parameter <value> cannot be nil.
|
||||
func (t *Bytes) Set(value []byte) (old []byte) {
|
||||
old = t.Val()
|
||||
t.val.Store(value)
|
||||
t.value.Store(value)
|
||||
return
|
||||
}
|
||||
|
||||
// Val atomically loads t.value.
|
||||
func (t *Bytes) Val() []byte {
|
||||
if s := t.val.Load(); s != nil {
|
||||
if s := t.value.Load(); s != nil {
|
||||
return s.([]byte)
|
||||
}
|
||||
return nil
|
||||
|
||||
@ -7,47 +7,53 @@
|
||||
package gtype
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
"github.com/gogf/gf/g/encoding/gbinary"
|
||||
"math"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type Float32 struct {
|
||||
val uint32
|
||||
value uint32
|
||||
}
|
||||
|
||||
// NewFloat32 returns a concurrent-safe object for float32 type,
|
||||
// with given initial value <value>.
|
||||
func NewFloat32(value...float32) *Float32 {
|
||||
if len(value) > 0 {
|
||||
return &Float32{ val : float32ToUint32InBits(value[0]) }
|
||||
return &Float32{
|
||||
value : math.Float32bits(value[0]),
|
||||
}
|
||||
}
|
||||
return &Float32{}
|
||||
}
|
||||
|
||||
// Clone clones and returns a new concurrent-safe object for float32 type.
|
||||
func (t *Float32) Clone() *Float32 {
|
||||
return NewFloat32(t.Val())
|
||||
}
|
||||
|
||||
// Set atomically stores value into t.value and returns the previous t.value value.
|
||||
func (t *Float32) Set(value float32) (old float32) {
|
||||
return uint32ToFloat32InBits(atomic.SwapUint32(&t.val, float32ToUint32InBits(value)))
|
||||
return math.Float32frombits(atomic.SwapUint32(&t.value, math.Float32bits(value)))
|
||||
}
|
||||
|
||||
// Val atomically loads t.value.
|
||||
func (t *Float32) Val() float32 {
|
||||
return uint32ToFloat32InBits(atomic.LoadUint32(&t.val))
|
||||
return math.Float32frombits(atomic.LoadUint32(&t.value))
|
||||
}
|
||||
|
||||
func (t *Float32) Add(delta float32) float32 {
|
||||
return uint32ToFloat32InBits(atomic.AddUint32(&t.val, float32ToUint32InBits(delta)))
|
||||
}
|
||||
|
||||
// 通过二进制的方式将float32转换为uint32(都是32bits)
|
||||
func float32ToUint32InBits(value float32) uint32 {
|
||||
b := gbinary.Encode(value)
|
||||
i := gbinary.DecodeToUint32(b)
|
||||
return i
|
||||
}
|
||||
|
||||
// 通过二进制的方式将uint32转换为float32(都是32bits)
|
||||
func uint32ToFloat32InBits(value uint32) float32 {
|
||||
b := gbinary.Encode(value)
|
||||
f := gbinary.DecodeToFloat32(b)
|
||||
return f
|
||||
// Add atomically adds delta to t.value and returns the new value.
|
||||
func (t *Float32) Add(delta float32) (new float32) {
|
||||
for {
|
||||
old := math.Float32frombits(t.value)
|
||||
new = old + delta
|
||||
if atomic.CompareAndSwapUint32(
|
||||
(*uint32)(unsafe.Pointer(&t.value)),
|
||||
math.Float32bits(old),
|
||||
math.Float32bits(new),
|
||||
) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -7,47 +7,53 @@
|
||||
package gtype
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
"github.com/gogf/gf/g/encoding/gbinary"
|
||||
"math"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type Float64 struct {
|
||||
val uint64
|
||||
value uint64
|
||||
}
|
||||
|
||||
// NewFloat64 returns a concurrent-safe object for float64 type,
|
||||
// with given initial value <value>.
|
||||
func NewFloat64(value...float64) *Float64 {
|
||||
if len(value) > 0 {
|
||||
return &Float64{ val : float64ToUint64InBits(value[0]) }
|
||||
return &Float64{
|
||||
value : math.Float64bits(value[0]),
|
||||
}
|
||||
}
|
||||
return &Float64{}
|
||||
}
|
||||
|
||||
// Clone clones and returns a new concurrent-safe object for float64 type.
|
||||
func (t *Float64) Clone() *Float64 {
|
||||
return NewFloat64(t.Val())
|
||||
}
|
||||
|
||||
// Set atomically stores value into t.value and returns the previous t.value value.
|
||||
func (t *Float64) Set(value float64) (old float64) {
|
||||
return uint64ToFloat64InBits(atomic.SwapUint64(&t.val, float64ToUint64InBits(value)))
|
||||
return math.Float64frombits(atomic.SwapUint64(&t.value, math.Float64bits(value)))
|
||||
}
|
||||
|
||||
// Val atomically loads t.value.
|
||||
func (t *Float64) Val() float64 {
|
||||
return uint64ToFloat64InBits(atomic.LoadUint64(&t.val))
|
||||
return math.Float64frombits(atomic.LoadUint64(&t.value))
|
||||
}
|
||||
|
||||
func (t *Float64) Add(delta float64) float64 {
|
||||
return uint64ToFloat64InBits(atomic.AddUint64(&t.val, float64ToUint64InBits(delta)))
|
||||
// Add atomically adds delta to t.value and returns the new value.
|
||||
func (t *Float64) Add(delta float64) (new float64) {
|
||||
for {
|
||||
old := math.Float64frombits(t.value)
|
||||
new = old + delta
|
||||
if atomic.CompareAndSwapUint64(
|
||||
(*uint64)(unsafe.Pointer(&t.value)),
|
||||
math.Float64bits(old),
|
||||
math.Float64bits(new),
|
||||
) {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 通过二进制的方式将float64转换为uint64(都是64bits)
|
||||
func float64ToUint64InBits(value float64) uint64 {
|
||||
b := gbinary.Encode(value)
|
||||
i := gbinary.DecodeToUint64(b)
|
||||
return i
|
||||
}
|
||||
|
||||
// 通过二进制的方式将uint64转换为float64(都是64bits)
|
||||
func uint64ToFloat64InBits(value uint64) float64 {
|
||||
b := gbinary.Encode(value)
|
||||
f := gbinary.DecodeToFloat64(b)
|
||||
return f
|
||||
}
|
||||
@ -4,11 +4,12 @@
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// Package gtype provides kinds of high performance, concurrent-safe/unsafe basic variable types.
|
||||
// Package gtype provides kinds of high performance and concurrent-safe basic variable types.
|
||||
package gtype
|
||||
|
||||
type Type = Interface
|
||||
|
||||
// See NewInterface.
|
||||
func New(value ... interface{}) *Type {
|
||||
return NewInterface(value...)
|
||||
}
|
||||
@ -11,30 +11,36 @@ import (
|
||||
)
|
||||
|
||||
type Int struct {
|
||||
val int64
|
||||
value int64
|
||||
}
|
||||
|
||||
// NewInt returns a concurrent-safe object for int type,
|
||||
// with given initial value <value>.
|
||||
func NewInt(value...int) *Int {
|
||||
if len(value) > 0 {
|
||||
return &Int{val:int64(value[0])}
|
||||
return &Int{
|
||||
value : int64(value[0]),
|
||||
}
|
||||
}
|
||||
return &Int{}
|
||||
}
|
||||
|
||||
// Clone clones and returns a new concurrent-safe object for int type.
|
||||
func (t *Int) Clone() *Int {
|
||||
return NewInt(t.Val())
|
||||
}
|
||||
|
||||
// 并发安全设置变量值,返回之前的旧值
|
||||
// Set atomically stores value into t.value and returns the previous t.value value.
|
||||
func (t *Int) Set(value int) (old int) {
|
||||
return int(atomic.SwapInt64(&t.val, int64(value)))
|
||||
return int(atomic.SwapInt64(&t.value, int64(value)))
|
||||
}
|
||||
|
||||
// Val atomically loads t.value.
|
||||
func (t *Int) Val() int {
|
||||
return int(atomic.LoadInt64(&t.val))
|
||||
return int(atomic.LoadInt64(&t.value))
|
||||
}
|
||||
|
||||
// 数值增加delta,并返回**新**的数值
|
||||
func (t *Int) Add(delta int) int {
|
||||
return int(atomic.AddInt64(&t.val, int64(delta)))
|
||||
// Add atomically adds delta to t.value and returns the new value.
|
||||
func (t *Int) Add(delta int) (new int) {
|
||||
return int(atomic.AddInt64(&t.value, int64(delta)))
|
||||
}
|
||||
@ -11,28 +11,36 @@ import (
|
||||
)
|
||||
|
||||
type Int32 struct {
|
||||
val int32
|
||||
value int32
|
||||
}
|
||||
|
||||
// NewInt32 returns a concurrent-safe object for int32 type,
|
||||
// with given initial value <value>.
|
||||
func NewInt32(value...int32) *Int32 {
|
||||
if len(value) > 0 {
|
||||
return &Int32{val: value[0]}
|
||||
return &Int32{
|
||||
value : value[0],
|
||||
}
|
||||
}
|
||||
return &Int32{}
|
||||
}
|
||||
|
||||
// Clone clones and returns a new concurrent-safe object for int32 type.
|
||||
func (t *Int32) Clone() *Int32 {
|
||||
return NewInt32(t.Val())
|
||||
}
|
||||
|
||||
// Set atomically stores value into t.value and returns the previous t.value value.
|
||||
func (t *Int32) Set(value int32) (old int32) {
|
||||
return atomic.SwapInt32(&t.val, value)
|
||||
return atomic.SwapInt32(&t.value, value)
|
||||
}
|
||||
|
||||
// Val atomically loads t.value.
|
||||
func (t *Int32) Val() int32 {
|
||||
return atomic.LoadInt32(&t.val)
|
||||
return atomic.LoadInt32(&t.value)
|
||||
}
|
||||
|
||||
func (t *Int32) Add(delta int32) int32 {
|
||||
return atomic.AddInt32(&t.val, delta)
|
||||
// Add atomically adds delta to t.value and returns the new value.
|
||||
func (t *Int32) Add(delta int32) (new int32) {
|
||||
return atomic.AddInt32(&t.value, delta)
|
||||
}
|
||||
@ -11,28 +11,36 @@ import (
|
||||
)
|
||||
|
||||
type Int64 struct {
|
||||
val int64
|
||||
value int64
|
||||
}
|
||||
|
||||
// NewInt64 returns a concurrent-safe object for int64 type,
|
||||
// with given initial value <value>.
|
||||
func NewInt64(value...int64) *Int64 {
|
||||
if len(value) > 0 {
|
||||
return &Int64{val:value[0]}
|
||||
return &Int64{
|
||||
value : value[0],
|
||||
}
|
||||
}
|
||||
return &Int64{}
|
||||
}
|
||||
|
||||
// Clone clones and returns a new concurrent-safe object for int64 type.
|
||||
func (t *Int64) Clone() *Int64 {
|
||||
return NewInt64(t.Val())
|
||||
}
|
||||
|
||||
// Set atomically stores value into t.value and returns the previous t.value value.
|
||||
func (t *Int64) Set(value int64) (old int64) {
|
||||
return atomic.SwapInt64(&t.val, value)
|
||||
return atomic.SwapInt64(&t.value, value)
|
||||
}
|
||||
|
||||
// Val atomically loads t.value.
|
||||
func (t *Int64) Val() int64 {
|
||||
return atomic.LoadInt64(&t.val)
|
||||
return atomic.LoadInt64(&t.value)
|
||||
}
|
||||
|
||||
// Add atomically adds delta to t.value and returns the new value.
|
||||
func (t *Int64) Add(delta int64) int64 {
|
||||
return atomic.AddInt64(&t.val, delta)
|
||||
return atomic.AddInt64(&t.value, delta)
|
||||
}
|
||||
@ -10,32 +10,34 @@ import (
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
// 比较通用的并发安全数据类型
|
||||
type Interface struct {
|
||||
val atomic.Value
|
||||
value atomic.Value
|
||||
}
|
||||
|
||||
// NewInterface returns a concurrent-safe object for interface{} type,
|
||||
// with given initial value <value>.
|
||||
func NewInterface(value...interface{}) *Interface {
|
||||
t := &Interface{}
|
||||
if len(value) > 0 && value[0] != nil {
|
||||
t.val.Store(value[0])
|
||||
t.value.Store(value[0])
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// Clone clones and returns a new concurrent-safe object for interface{} type.
|
||||
func (t *Interface) Clone() *Interface {
|
||||
return NewInterface(t.Val())
|
||||
}
|
||||
|
||||
// Set atomically stores value into t.value and returns the previous t.value value.
|
||||
// Note: The parameter <value> cannot be nil.
|
||||
func (t *Interface) Set(value interface{}) (old interface{}) {
|
||||
if value == nil {
|
||||
return
|
||||
}
|
||||
old = t.Val()
|
||||
t.val.Store(value)
|
||||
t.value.Store(value)
|
||||
return
|
||||
}
|
||||
|
||||
// Val atomically loads t.value.
|
||||
func (t *Interface) Val() interface{} {
|
||||
return t.val.Load()
|
||||
return t.value.Load()
|
||||
}
|
||||
@ -11,29 +11,34 @@ import (
|
||||
)
|
||||
|
||||
type String struct {
|
||||
val atomic.Value
|
||||
value atomic.Value
|
||||
}
|
||||
|
||||
// NewString returns a concurrent-safe object for string type,
|
||||
// with given initial value <value>.
|
||||
func NewString(value...string) *String {
|
||||
t := &String{}
|
||||
if len(value) > 0 {
|
||||
t.val.Store(value[0])
|
||||
t.value.Store(value[0])
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// Clone clones and returns a new concurrent-safe object for string type.
|
||||
func (t *String) Clone() *String {
|
||||
return NewString(t.Val())
|
||||
}
|
||||
|
||||
// Set atomically stores value into t.value and returns the previous t.value value.
|
||||
func (t *String) Set(value string) (old string) {
|
||||
old = t.Val()
|
||||
t.val.Store(value)
|
||||
t.value.Store(value)
|
||||
return
|
||||
}
|
||||
|
||||
// Val atomically loads t.value.
|
||||
func (t *String) Val() string {
|
||||
s := t.val.Load()
|
||||
s := t.value.Load()
|
||||
if s != nil {
|
||||
return s.(string)
|
||||
}
|
||||
|
||||
@ -11,28 +11,36 @@ import (
|
||||
)
|
||||
|
||||
type Uint struct {
|
||||
val uint64
|
||||
value uint64
|
||||
}
|
||||
|
||||
// NewUint returns a concurrent-safe object for uint type,
|
||||
// with given initial value <value>.
|
||||
func NewUint(value...uint) *Uint {
|
||||
if len(value) > 0 {
|
||||
return &Uint{val:uint64(value[0])}
|
||||
return &Uint{
|
||||
value : uint64(value[0]),
|
||||
}
|
||||
}
|
||||
return &Uint{}
|
||||
}
|
||||
|
||||
// Clone clones and returns a new concurrent-safe object for uint type.
|
||||
func (t *Uint) Clone() *Uint {
|
||||
return NewUint(t.Val())
|
||||
}
|
||||
|
||||
// Set atomically stores value into t.value and returns the previous t.value value.
|
||||
func (t *Uint) Set(value uint) (old uint) {
|
||||
return uint(atomic.SwapUint64(&t.val, uint64(value)))
|
||||
return uint(atomic.SwapUint64(&t.value, uint64(value)))
|
||||
}
|
||||
|
||||
// Val atomically loads t.value.
|
||||
func (t *Uint) Val() uint {
|
||||
return uint(atomic.LoadUint64(&t.val))
|
||||
return uint(atomic.LoadUint64(&t.value))
|
||||
}
|
||||
|
||||
func (t *Uint) Add(delta uint) int {
|
||||
return int(atomic.AddUint64(&t.val, uint64(delta)))
|
||||
// Add atomically adds delta to t.value and returns the new value.
|
||||
func (t *Uint) Add(delta uint) (new uint) {
|
||||
return uint(atomic.AddUint64(&t.value, uint64(delta)))
|
||||
}
|
||||
@ -11,28 +11,36 @@ import (
|
||||
)
|
||||
|
||||
type Uint32 struct {
|
||||
val uint32
|
||||
value uint32
|
||||
}
|
||||
|
||||
// NewUint32 returns a concurrent-safe object for uint32 type,
|
||||
// with given initial value <value>.
|
||||
func NewUint32(value...uint32) *Uint32 {
|
||||
if len(value) > 0 {
|
||||
return &Uint32{val:value[0]}
|
||||
return &Uint32{
|
||||
value : value[0],
|
||||
}
|
||||
}
|
||||
return &Uint32{}
|
||||
}
|
||||
|
||||
// Clone clones and returns a new concurrent-safe object for uint32 type.
|
||||
func (t *Uint32) Clone() *Uint32 {
|
||||
return NewUint32(t.Val())
|
||||
}
|
||||
|
||||
// Set atomically stores value into t.value and returns the previous t.value value.
|
||||
func (t *Uint32) Set(value uint32) (old uint32) {
|
||||
return atomic.SwapUint32(&t.val, value)
|
||||
return atomic.SwapUint32(&t.value, value)
|
||||
}
|
||||
|
||||
// Val atomically loads t.value.
|
||||
func (t *Uint32) Val() uint32 {
|
||||
return atomic.LoadUint32(&t.val)
|
||||
return atomic.LoadUint32(&t.value)
|
||||
}
|
||||
|
||||
func (t *Uint32) Add(delta uint32) uint32 {
|
||||
return atomic.AddUint32(&t.val, delta)
|
||||
// Add atomically adds delta to t.value and returns the new value.
|
||||
func (t *Uint32) Add(delta uint32) (new uint32) {
|
||||
return atomic.AddUint32(&t.value, delta)
|
||||
}
|
||||
@ -11,28 +11,36 @@ import (
|
||||
)
|
||||
|
||||
type Uint64 struct {
|
||||
val uint64
|
||||
value uint64
|
||||
}
|
||||
|
||||
// NewUint64 returns a concurrent-safe object for uint64 type,
|
||||
// with given initial value <value>.
|
||||
func NewUint64(value...uint64) *Uint64 {
|
||||
if len(value) > 0 {
|
||||
return &Uint64{val:value[0]}
|
||||
return &Uint64{
|
||||
value : value[0],
|
||||
}
|
||||
}
|
||||
return &Uint64{}
|
||||
}
|
||||
|
||||
// Clone clones and returns a new concurrent-safe object for uint64 type.
|
||||
func (t *Uint64) Clone() *Uint64 {
|
||||
return NewUint64(t.Val())
|
||||
}
|
||||
|
||||
// Set atomically stores value into t.value and returns the previous t.value value.
|
||||
func (t *Uint64) Set(value uint64) (old uint64) {
|
||||
return atomic.SwapUint64(&t.val, value)
|
||||
return atomic.SwapUint64(&t.value, value)
|
||||
}
|
||||
|
||||
// Val atomically loads t.value.
|
||||
func (t *Uint64) Val() uint64 {
|
||||
return atomic.LoadUint64(&t.val)
|
||||
return atomic.LoadUint64(&t.value)
|
||||
}
|
||||
|
||||
func (t *Uint64) Add(delta uint64) uint64 {
|
||||
return atomic.AddUint64(&t.val, delta)
|
||||
// Add atomically adds delta to t.value and returns the new value.
|
||||
func (t *Uint64) Add(delta uint64) (new uint64) {
|
||||
return atomic.AddUint64(&t.value, delta)
|
||||
}
|
||||
62
g/crypto/gaes/gaes_test.go
Normal file
62
g/crypto/gaes/gaes_test.go
Normal file
@ -0,0 +1,62 @@
|
||||
// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// go test *.go -bench=".*"
|
||||
|
||||
package gaes_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/g/crypto/gaes"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
)
|
||||
|
||||
var (
|
||||
content = []byte("pibigstar")
|
||||
// iv 长度必须等于blockSize,只能为16
|
||||
iv = []byte("Hello My GoFrame")
|
||||
key_16 = []byte("1234567891234567")
|
||||
key_24 = []byte("123456789123456789123456")
|
||||
key_32 = []byte("12345678912345678912345678912345")
|
||||
)
|
||||
|
||||
func TestEncrypt(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
_, err := gaes.Encrypt(content, key_16)
|
||||
gtest.Assert(err, nil)
|
||||
_, err = gaes.Encrypt(content, key_24)
|
||||
gtest.Assert(err, nil)
|
||||
_, err = gaes.Encrypt(content, key_32)
|
||||
gtest.Assert(err, nil)
|
||||
_, err = gaes.Encrypt(content, key_16, iv)
|
||||
gtest.Assert(err, nil)
|
||||
})
|
||||
}
|
||||
|
||||
func TestDecrypt(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
encrypt, err := gaes.Encrypt(content, key_16)
|
||||
decrypt, err := gaes.Decrypt(encrypt, key_16)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(string(decrypt), string(content))
|
||||
|
||||
encrypt, err = gaes.Encrypt(content, key_24)
|
||||
decrypt, err = gaes.Decrypt(encrypt, key_24)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(string(decrypt), string(content))
|
||||
|
||||
encrypt, err = gaes.Encrypt(content, key_32)
|
||||
decrypt, err = gaes.Decrypt(encrypt, key_32)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(string(decrypt), string(content))
|
||||
|
||||
encrypt, err = gaes.Encrypt(content, key_32, iv)
|
||||
decrypt, err = gaes.Decrypt(encrypt, key_32, iv)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(string(decrypt), string(content))
|
||||
})
|
||||
}
|
||||
27
g/crypto/gcrc32/gcrc32_test.go
Normal file
27
g/crypto/gcrc32/gcrc32_test.go
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// go test *.go -bench=".*"
|
||||
|
||||
package gcrc32_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/g/crypto/gcrc32"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
)
|
||||
|
||||
func TestEncrypt(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
s := "pibigstar"
|
||||
result := 693191136
|
||||
encrypt1 := gcrc32.EncryptString(s)
|
||||
encrypt2 := gcrc32.EncryptBytes([]byte(s))
|
||||
gtest.AssertEQ(int(encrypt1), result)
|
||||
gtest.AssertEQ(int(encrypt2), result)
|
||||
})
|
||||
}
|
||||
@ -1,185 +1,239 @@
|
||||
package gdes_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/g/crypto/gdes"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
)
|
||||
|
||||
func TestDesECB(t *testing.T){
|
||||
{
|
||||
var (
|
||||
errKey = []byte("1111111111111234123456789")
|
||||
errIv = []byte("123456789")
|
||||
errPadding = 5
|
||||
)
|
||||
|
||||
func TestDesECB(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
key := []byte("11111111")
|
||||
text := []byte("12345678")
|
||||
padding := gdes.NOPADDING
|
||||
result := "858b176da8b12503"
|
||||
// encrypt test
|
||||
cipherText, err := gdes.DesECBEncrypt(key, text, padding)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
gtest.AssertEQ(err, nil)
|
||||
gtest.AssertEQ(hex.EncodeToString(cipherText),result)
|
||||
// decrypt test
|
||||
clearText, err := gdes.DesECBDecrypt(key, cipherText, padding)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
gtest.AssertEQ(err, nil)
|
||||
gtest.AssertEQ(string(clearText), "12345678")
|
||||
|
||||
if bytes.Equal(clearText, text) == false {
|
||||
t.Errorf("text:%v, clearText:%v", hex.EncodeToString(text), hex.EncodeToString(clearText))
|
||||
}
|
||||
fmt.Println("clearText:", hex.EncodeToString(clearText), "cipherText:", hex.EncodeToString(cipherText))
|
||||
// encrypt err test. when throw exception,the err is not equal nil and the string is nil
|
||||
errEncrypt, err := gdes.DesECBEncrypt(key, text, errPadding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errEncrypt, nil)
|
||||
errEncrypt, err = gdes.DesECBEncrypt(errKey, text, padding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errEncrypt, nil)
|
||||
// err decrypt test.
|
||||
errDecrypt, err := gdes.DesECBDecrypt(errKey, cipherText, padding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errDecrypt, nil)
|
||||
errDecrypt, err = gdes.DesECBDecrypt(key, cipherText, errPadding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errDecrypt, nil)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
gtest.Case(t, func() {
|
||||
key := []byte("11111111")
|
||||
text := []byte("12345678")
|
||||
padding := gdes.PKCS5PADDING
|
||||
errPadding := 5
|
||||
result := "858b176da8b12503ad6a88b4fa37833d"
|
||||
cipherText, err := gdes.DesECBEncrypt(key, text, padding)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
gtest.AssertEQ(err,nil)
|
||||
gtest.AssertEQ(hex.EncodeToString(cipherText),result)
|
||||
// decrypt test
|
||||
clearText, err := gdes.DesECBDecrypt(key, cipherText, padding)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
gtest.AssertEQ(err,nil)
|
||||
gtest.AssertEQ(string(clearText),"12345678")
|
||||
|
||||
if bytes.Equal(clearText, text) == false {
|
||||
t.Errorf("text:%v, clearText:%v", hex.EncodeToString(text), hex.EncodeToString(clearText))
|
||||
}
|
||||
fmt.Println("clearText:", hex.EncodeToString(clearText), "cipherText:", hex.EncodeToString(cipherText))
|
||||
}
|
||||
// err test
|
||||
errEncrypt, err := gdes.DesECBEncrypt(key, text, errPadding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errEncrypt, nil)
|
||||
errDecrypt, err := gdes.DesECBDecrypt(errKey, cipherText, padding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errDecrypt, nil)
|
||||
})
|
||||
}
|
||||
|
||||
func Test3DesECB(t *testing.T){
|
||||
{
|
||||
func Test3DesECB(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
key := []byte("1111111111111234")
|
||||
text := []byte("1234567812345678")
|
||||
padding := gdes.NOPADDING
|
||||
result := "a23ee24b98c26263a23ee24b98c26263"
|
||||
// encrypt test
|
||||
cipherText, err := gdes.TripleDesECBEncrypt(key, text, padding)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
gtest.AssertEQ(err,nil)
|
||||
gtest.AssertEQ(hex.EncodeToString(cipherText),result)
|
||||
// decrypt test
|
||||
clearText, err := gdes.TripleDesECBDecrypt(key, cipherText, padding)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
gtest.AssertEQ(err,nil)
|
||||
gtest.AssertEQ(string(clearText),"1234567812345678")
|
||||
// err test
|
||||
errEncrypt, err := gdes.DesECBEncrypt(key, text, errPadding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errEncrypt, nil)
|
||||
})
|
||||
|
||||
if bytes.Equal(clearText, text) == false {
|
||||
t.Errorf("text:%v, clearText:%v", hex.EncodeToString(text), hex.EncodeToString(clearText))
|
||||
}
|
||||
fmt.Println("key:", hex.EncodeToString(key),"clearText:", hex.EncodeToString(clearText), "cipherText:", hex.EncodeToString(cipherText))
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
gtest.Case(t, func() {
|
||||
key := []byte("111111111111123412345678")
|
||||
text := []byte("123456789")
|
||||
padding := gdes.PKCS5PADDING
|
||||
errPadding := 5
|
||||
result := "37989b1effc07a6d00ff89a7d052e79f"
|
||||
// encrypt test
|
||||
cipherText, err := gdes.TripleDesECBEncrypt(key, text, padding)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
gtest.AssertEQ(err,nil)
|
||||
gtest.AssertEQ(hex.EncodeToString(cipherText),result)
|
||||
// decrypt test
|
||||
clearText, err := gdes.TripleDesECBDecrypt(key, cipherText, padding)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
if bytes.Equal(clearText, text) == false {
|
||||
t.Errorf("text:%v, clearText:%v", hex.EncodeToString(text), hex.EncodeToString(clearText))
|
||||
}
|
||||
fmt.Println("key:", hex.EncodeToString(key),"clearText:", hex.EncodeToString(clearText), "cipherText:", hex.EncodeToString(cipherText))
|
||||
}
|
||||
gtest.AssertEQ(err,nil)
|
||||
gtest.AssertEQ(string(clearText),"123456789")
|
||||
// err test, when key is err, but text and padding is right
|
||||
errEncrypt, err := gdes.TripleDesECBEncrypt(errKey, text, padding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errEncrypt, nil)
|
||||
// when padding is err,but key and text is right
|
||||
errEncrypt, err = gdes.TripleDesECBEncrypt(key, text, errPadding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errEncrypt, nil)
|
||||
// decrypt err test,when key is err
|
||||
errEncrypt, err = gdes.TripleDesECBDecrypt(errKey, text, padding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errEncrypt, nil)
|
||||
})
|
||||
}
|
||||
|
||||
func TestDesCBC(t *testing.T){
|
||||
{
|
||||
func TestDesCBC(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
key := []byte("11111111")
|
||||
text := []byte("1234567812345678")
|
||||
padding := gdes.NOPADDING
|
||||
iv := []byte("12345678")
|
||||
cipherText, err := gdes.DesCBCEncrypt(key, text, iv,padding)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
result := "40826a5800608c87585ca7c9efabee47"
|
||||
// encrypt test
|
||||
cipherText, err := gdes.DesCBCEncrypt(key, text, iv, padding)
|
||||
gtest.AssertEQ(err,nil)
|
||||
gtest.AssertEQ(hex.EncodeToString(cipherText),result)
|
||||
// decrypt test
|
||||
clearText, err := gdes.DesCBCDecrypt(key, cipherText, iv, padding)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
gtest.AssertEQ(err,nil)
|
||||
gtest.AssertEQ(string(clearText),"1234567812345678")
|
||||
// encrypt err test.
|
||||
errEncrypt, err := gdes.DesCBCEncrypt(errKey, text, iv, padding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errEncrypt, nil)
|
||||
// the iv is err
|
||||
errEncrypt, err = gdes.DesCBCEncrypt(key, text, errIv, padding)
|
||||
//gtest.AssertNE(err,nil)
|
||||
gtest.AssertEQ(errEncrypt, nil)
|
||||
// the padding is err
|
||||
errEncrypt, err = gdes.DesCBCEncrypt(key, text, iv, errPadding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errEncrypt, nil)
|
||||
// decrypt err test. the key is err
|
||||
errDecrypt, err := gdes.DesCBCDecrypt(errKey, cipherText, iv, padding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errDecrypt, nil)
|
||||
// the iv is err
|
||||
errDecrypt, err = gdes.DesCBCDecrypt(key, cipherText, errIv, padding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errDecrypt, nil)
|
||||
// the padding is err
|
||||
errDecrypt, err = gdes.DesCBCDecrypt(key, cipherText, iv, errPadding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errDecrypt, nil)
|
||||
})
|
||||
|
||||
if bytes.Equal(clearText, text) == false {
|
||||
t.Errorf("text:%v, clearText:%v", hex.EncodeToString(text), hex.EncodeToString(clearText))
|
||||
}
|
||||
fmt.Println("key:", hex.EncodeToString(key),"clearText:", hex.EncodeToString(clearText), "cipherText:", hex.EncodeToString(cipherText))
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
gtest.Case(t, func() {
|
||||
key := []byte("11111111")
|
||||
text := []byte("12345678")
|
||||
padding := gdes.PKCS5PADDING
|
||||
iv := []byte("12345678")
|
||||
result := "40826a5800608c87100a25d86ac7c52c"
|
||||
// encrypt test
|
||||
cipherText, err := gdes.DesCBCEncrypt(key, text, iv, padding)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
gtest.AssertEQ(err,nil)
|
||||
gtest.AssertEQ(hex.EncodeToString(cipherText),result)
|
||||
// decrypt test
|
||||
clearText, err := gdes.DesCBCDecrypt(key, cipherText, iv, padding)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
if bytes.Equal(clearText, text) == false {
|
||||
t.Errorf("text:%v, clearText:%v", hex.EncodeToString(text), hex.EncodeToString(clearText))
|
||||
}
|
||||
fmt.Println("key:", hex.EncodeToString(key),"clearText:", hex.EncodeToString(clearText), "cipherText:", hex.EncodeToString(cipherText))
|
||||
}
|
||||
gtest.AssertEQ(err,nil)
|
||||
gtest.AssertEQ(string(clearText),"12345678")
|
||||
// err test
|
||||
errEncrypt, err := gdes.DesCBCEncrypt(key, text, errIv, padding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errEncrypt, nil)
|
||||
})
|
||||
}
|
||||
|
||||
func Test3DesCBC(t *testing.T){
|
||||
{
|
||||
func Test3DesCBC(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
key := []byte("1111111112345678")
|
||||
text := []byte("1234567812345678")
|
||||
padding := gdes.NOPADDING
|
||||
iv := []byte("12345678")
|
||||
cipherText, err := gdes.TripleDesCBCEncrypt(key, text, iv,padding)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
result := "bfde1394e265d5f738d5cab170c77c88"
|
||||
// encrypt test
|
||||
cipherText, err := gdes.TripleDesCBCEncrypt(key, text, iv, padding)
|
||||
gtest.AssertEQ(err,nil)
|
||||
gtest.AssertEQ(hex.EncodeToString(cipherText),result)
|
||||
// decrypt test
|
||||
clearText, err := gdes.TripleDesCBCDecrypt(key, cipherText, iv, padding)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
if bytes.Equal(clearText, text) == false {
|
||||
t.Errorf("text:%v, clearText:%v", hex.EncodeToString(text), hex.EncodeToString(clearText))
|
||||
}
|
||||
fmt.Println("key:", hex.EncodeToString(key),"clearText:", hex.EncodeToString(clearText), "cipherText:", hex.EncodeToString(cipherText))
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
gtest.AssertEQ(err,nil)
|
||||
gtest.AssertEQ(string(clearText),"1234567812345678")
|
||||
// encrypt err test
|
||||
errEncrypt, err := gdes.TripleDesCBCEncrypt(errKey, text, iv, padding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errEncrypt, nil)
|
||||
// the iv is err
|
||||
errEncrypt, err = gdes.TripleDesCBCEncrypt(key, text, errIv, padding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errEncrypt, nil)
|
||||
// the padding is err
|
||||
errEncrypt, err = gdes.TripleDesCBCEncrypt(key, text, iv, errPadding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errEncrypt, nil)
|
||||
// decrypt err test
|
||||
errDecrypt, err := gdes.TripleDesCBCDecrypt(errKey, cipherText, iv, padding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errDecrypt, nil)
|
||||
// the iv is err
|
||||
errDecrypt, err = gdes.TripleDesCBCDecrypt(key, cipherText, errIv, padding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errDecrypt, nil)
|
||||
// the padding is err
|
||||
errDecrypt, err = gdes.TripleDesCBCDecrypt(key, cipherText, iv, errPadding)
|
||||
gtest.AssertNE(err, nil)
|
||||
gtest.AssertEQ(errDecrypt, nil)
|
||||
})
|
||||
gtest.Case(t, func() {
|
||||
key := []byte("111111111234567812345678")
|
||||
text := []byte("12345678")
|
||||
padding := gdes.PKCS5PADDING
|
||||
iv := []byte("12345678")
|
||||
result := "40826a5800608c87100a25d86ac7c52c"
|
||||
// encrypt test
|
||||
cipherText, err := gdes.TripleDesCBCEncrypt(key, text, iv, padding)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
|
||||
gtest.AssertEQ(err,nil)
|
||||
gtest.AssertEQ(hex.EncodeToString(cipherText),result)
|
||||
// decrypt test
|
||||
clearText, err := gdes.TripleDesCBCDecrypt(key, cipherText, iv, padding)
|
||||
if err != nil {
|
||||
t.Errorf("%v", err)
|
||||
}
|
||||
gtest.AssertEQ(err,nil)
|
||||
gtest.AssertEQ(string(clearText),"12345678")
|
||||
})
|
||||
|
||||
if bytes.Equal(clearText, text) == false {
|
||||
t.Errorf("text:%v, clearText:%v", hex.EncodeToString(text), hex.EncodeToString(clearText))
|
||||
}
|
||||
fmt.Println("key:", hex.EncodeToString(key),"clearText:", hex.EncodeToString(clearText), "cipherText:", hex.EncodeToString(cipherText))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
78
g/crypto/gmd5/gmd5_test.go
Normal file
78
g/crypto/gmd5/gmd5_test.go
Normal file
@ -0,0 +1,78 @@
|
||||
// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// go test *.go -bench=".*"
|
||||
|
||||
package gmd5_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/g/crypto/gmd5"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
)
|
||||
|
||||
var (
|
||||
s = "pibigstar"
|
||||
// online generated MD5 value
|
||||
result = "d175a1ff66aedde64344785f7f7a3df8"
|
||||
)
|
||||
|
||||
type user struct {
|
||||
name string
|
||||
password string
|
||||
age int
|
||||
}
|
||||
|
||||
func TestEncrypt(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
encryptString := gmd5.Encrypt(s)
|
||||
gtest.Assert(encryptString, result)
|
||||
|
||||
result := "1427562bb29f88a1161590b76398ab72"
|
||||
encrypt := gmd5.Encrypt(123456)
|
||||
gtest.AssertEQ(encrypt,result)
|
||||
})
|
||||
|
||||
gtest.Case(t, func() {
|
||||
user := &user{
|
||||
name: "派大星",
|
||||
password: "123456",
|
||||
age: 23,
|
||||
}
|
||||
result := "70917ebce8bd2f78c736cda63870fb39"
|
||||
encrypt := gmd5.Encrypt(user)
|
||||
gtest.AssertEQ(encrypt,result)
|
||||
})
|
||||
}
|
||||
|
||||
func TestEncryptString(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
encryptString := gmd5.EncryptString(s)
|
||||
gtest.Assert(encryptString, result)
|
||||
})
|
||||
}
|
||||
|
||||
func TestEncryptFile(t *testing.T) {
|
||||
path := "test.text"
|
||||
errorPath := "err.txt"
|
||||
result := "e6e6e1cd41895beebff16d5452dfce12"
|
||||
gtest.Case(t, func() {
|
||||
file, err := os.Create(path)
|
||||
defer os.Remove(path)
|
||||
defer file.Close()
|
||||
gtest.Assert(err, nil)
|
||||
file.Write([]byte("Hello Go Frame"))
|
||||
encryptFile := gmd5.EncryptFile(path)
|
||||
gtest.AssertEQ(encryptFile, result)
|
||||
// when the file is not exist,encrypt will return empty string
|
||||
errEncrypt := gmd5.EncryptFile(errorPath)
|
||||
gtest.AssertEQ(errEncrypt, "")
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
67
g/crypto/gsha1/gsha1_test.go
Normal file
67
g/crypto/gsha1/gsha1_test.go
Normal file
@ -0,0 +1,67 @@
|
||||
// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// go test *.go -bench=".*"
|
||||
|
||||
package gsha1_test
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/g/crypto/gsha1"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
)
|
||||
|
||||
type user struct {
|
||||
name string
|
||||
password string
|
||||
age int
|
||||
}
|
||||
|
||||
func TestEncrypt(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
user := &user{
|
||||
name: "派大星",
|
||||
password: "123456",
|
||||
age: 23,
|
||||
}
|
||||
result := "97386736e3ee4adee5ca595c78c12129f6032cad"
|
||||
encrypt := gsha1.Encrypt(user)
|
||||
gtest.AssertEQ(encrypt, result)
|
||||
})
|
||||
gtest.Case(t, func() {
|
||||
result := "5b4c1c2a08ca85ddd031ef8627414f4cb2620b41"
|
||||
s := gsha1.Encrypt("pibigstar")
|
||||
gtest.AssertEQ(s, result)
|
||||
})
|
||||
}
|
||||
|
||||
func TestEncryptString(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
result := "5b4c1c2a08ca85ddd031ef8627414f4cb2620b41"
|
||||
s := gsha1.EncryptString("pibigstar")
|
||||
gtest.AssertEQ(s, result)
|
||||
})
|
||||
}
|
||||
|
||||
func TestEncryptFile(t *testing.T) {
|
||||
path := "test.text"
|
||||
errPath := "err.text"
|
||||
gtest.Case(t, func() {
|
||||
result := "8b05d3ba24b8d2374b8f5149d9f3fbada14ea984"
|
||||
file, err := os.Create(path)
|
||||
defer os.Remove(path)
|
||||
defer file.Close()
|
||||
gtest.Assert(err, nil)
|
||||
file.Write([]byte("Hello Go Frame"))
|
||||
encryptFile := gsha1.EncryptFile(path)
|
||||
gtest.AssertEQ(encryptFile, result)
|
||||
// when the file is not exist,encrypt will return empty string
|
||||
errEncrypt := gsha1.EncryptFile(errPath)
|
||||
gtest.AssertEQ(errEncrypt,"")
|
||||
})
|
||||
}
|
||||
334
g/os/gfile/gfile_contents_test.go
Normal file
334
g/os/gfile/gfile_contents_test.go
Normal file
@ -0,0 +1,334 @@
|
||||
package gfile_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// 创建测试文件
|
||||
func createTestFile(filename, content string) error {
|
||||
TempDir := testpath()
|
||||
err := ioutil.WriteFile(TempDir+filename, []byte(content), 0666)
|
||||
return err
|
||||
}
|
||||
|
||||
// 测试完删除文件或目录
|
||||
func delTestFiles(filenames string) {
|
||||
os.RemoveAll(testpath() + filenames)
|
||||
}
|
||||
|
||||
// 创建目录
|
||||
func createDir(paths string) {
|
||||
TempDir := testpath()
|
||||
os.Mkdir(TempDir+paths, 0777)
|
||||
}
|
||||
|
||||
// 统一格式化文件目录为"/"
|
||||
func formatpaths(paths []string) []string {
|
||||
for k, v := range paths {
|
||||
paths[k] = filepath.ToSlash(v)
|
||||
paths[k] = strings.Replace(paths[k], "./", "/", 1)
|
||||
}
|
||||
|
||||
return paths
|
||||
}
|
||||
|
||||
// 统一格式化文件目录为"/"
|
||||
func formatpath(paths string) string {
|
||||
paths = filepath.ToSlash(paths)
|
||||
paths = strings.Replace(paths, "./", "/", 1)
|
||||
return paths
|
||||
}
|
||||
|
||||
// 指定返回要测试的目录
|
||||
func testpath() string {
|
||||
return os.TempDir()
|
||||
}
|
||||
|
||||
func TestGetContents(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
|
||||
var (
|
||||
filepaths string = "/testfile_t1.txt"
|
||||
)
|
||||
createTestFile(filepaths, "my name is jroam")
|
||||
defer delTestFiles(filepaths)
|
||||
|
||||
gtest.Assert(gfile.GetContents(testpath()+filepaths), "my name is jroam")
|
||||
gtest.Assert(gfile.GetContents(""), "")
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetBinContents(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
filepaths1 string = "/testfile_t1.txt" // 文件存在时
|
||||
filepaths2 string = testpath() + "/testfile_t1_no.txt" // 文件不存在时
|
||||
readcontent []byte
|
||||
str1 string = "my name is jroam"
|
||||
)
|
||||
createTestFile(filepaths1, str1)
|
||||
defer delTestFiles(filepaths1)
|
||||
readcontent = gfile.GetBinContents(testpath() + filepaths1)
|
||||
gtest.Assert(readcontent, []byte(str1))
|
||||
|
||||
readcontent = gfile.GetBinContents(filepaths2)
|
||||
gtest.Assert(string(readcontent), "")
|
||||
|
||||
gtest.Assert(string(gfile.GetBinContents(filepaths2)), "")
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// 截断文件为指定的大小
|
||||
func TestTruncate(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
filepaths1 string = "/testfile_GetContentsyyui.txt" //文件存在时
|
||||
err error
|
||||
files *os.File
|
||||
)
|
||||
createTestFile(filepaths1, "abcdefghijkmln")
|
||||
defer delTestFiles(filepaths1)
|
||||
err = gfile.Truncate(testpath()+filepaths1, 10)
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
//=========================检查修改文后的大小,是否与期望一致
|
||||
files, err = os.Open(testpath() + filepaths1)
|
||||
defer files.Close()
|
||||
gtest.Assert(err, nil)
|
||||
fileinfo, err2 := files.Stat()
|
||||
gtest.Assert(err2, nil)
|
||||
gtest.Assert(fileinfo.Size(), 10)
|
||||
|
||||
//====测试当为空时,是否报错
|
||||
err = gfile.Truncate("", 10)
|
||||
gtest.AssertNE(err, nil)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestPutContents(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
filepaths string = "/testfile_PutContents.txt"
|
||||
err error
|
||||
readcontent []byte
|
||||
)
|
||||
createTestFile(filepaths, "a")
|
||||
defer delTestFiles(filepaths)
|
||||
|
||||
err = gfile.PutContents(testpath()+filepaths, "test!")
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
//==================判断是否真正写入
|
||||
readcontent, err = ioutil.ReadFile(testpath() + filepaths)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(string(readcontent), "test!")
|
||||
|
||||
err = gfile.PutContents("", "test!")
|
||||
gtest.AssertNE(err, nil)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestPutContentsAppend(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
filepaths string = "/testfile_PutContents.txt"
|
||||
err error
|
||||
readcontent []byte
|
||||
)
|
||||
|
||||
createTestFile(filepaths, "a")
|
||||
defer delTestFiles(filepaths)
|
||||
err = gfile.PutContentsAppend(testpath()+filepaths, "hello")
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
//==================判断是否真正写入
|
||||
readcontent, err = ioutil.ReadFile(testpath() + filepaths)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(string(readcontent), "ahello")
|
||||
|
||||
err = gfile.PutContentsAppend("", "hello")
|
||||
gtest.AssertNE(err, nil)
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestPutBinContents(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
filepaths string = "/testfile_PutContents.txt"
|
||||
err error
|
||||
readcontent []byte
|
||||
)
|
||||
createTestFile(filepaths, "a")
|
||||
defer delTestFiles(filepaths)
|
||||
|
||||
err = gfile.PutBinContents(testpath()+filepaths, []byte("test!!"))
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
// 判断是否真正写入
|
||||
readcontent, err = ioutil.ReadFile(testpath() + filepaths)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(string(readcontent), "test!!")
|
||||
|
||||
err = gfile.PutBinContents("", []byte("test!!"))
|
||||
gtest.AssertNE(err, nil)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestPutBinContentsAppend(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
filepaths string = "/testfile_PutContents.txt" //原文件内容: yy
|
||||
err error
|
||||
readcontent []byte
|
||||
)
|
||||
createTestFile(filepaths, "test!!")
|
||||
defer delTestFiles(filepaths)
|
||||
err = gfile.PutBinContentsAppend(testpath()+filepaths, []byte("word"))
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
// 判断是否真正写入
|
||||
readcontent, err = ioutil.ReadFile(testpath() + filepaths)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(string(readcontent), "test!!word")
|
||||
|
||||
err = gfile.PutBinContentsAppend("", []byte("word"))
|
||||
gtest.AssertNE(err, nil)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetBinContentsByTwoOffsetsByPath(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
filepaths string = "/testfile_GetContents.txt" // 文件内容: abcdefghijk
|
||||
readcontent []byte
|
||||
)
|
||||
|
||||
createTestFile(filepaths, "abcdefghijk")
|
||||
defer delTestFiles(filepaths)
|
||||
readcontent = gfile.GetBinContentsByTwoOffsetsByPath(testpath()+filepaths, 2, 5)
|
||||
|
||||
gtest.Assert(string(readcontent), "cde")
|
||||
|
||||
readcontent = gfile.GetBinContentsByTwoOffsetsByPath("", 2, 5)
|
||||
gtest.Assert(len(readcontent), 0)
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestGetNextCharOffsetByPath(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
filepaths string = "/testfile_GetContents.txt" // 文件内容: abcdefghijk
|
||||
localindex int64
|
||||
)
|
||||
createTestFile(filepaths, "abcdefghijk")
|
||||
defer delTestFiles(filepaths)
|
||||
localindex = gfile.GetNextCharOffsetByPath(testpath()+filepaths, 'd', 1)
|
||||
gtest.Assert(localindex, 3)
|
||||
|
||||
localindex = gfile.GetNextCharOffsetByPath("", 'd', 1)
|
||||
gtest.Assert(localindex, -1)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetNextCharOffset(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
localindex int64
|
||||
)
|
||||
reader := strings.NewReader("helloword")
|
||||
|
||||
localindex = gfile.GetNextCharOffset(reader, 'w', 1)
|
||||
gtest.Assert(localindex, 5)
|
||||
|
||||
localindex = gfile.GetNextCharOffset(reader, 'j', 1)
|
||||
gtest.Assert(localindex, -1)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetBinContentsByTwoOffsets(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
reads []byte
|
||||
)
|
||||
reader := strings.NewReader("helloword")
|
||||
|
||||
reads = gfile.GetBinContentsByTwoOffsets(reader, 1, 3)
|
||||
gtest.Assert(string(reads), "el")
|
||||
|
||||
reads = gfile.GetBinContentsByTwoOffsets(reader, 10, 30)
|
||||
gtest.Assert(string(reads), "")
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetBinContentsTilChar(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
reads []byte
|
||||
indexs int64
|
||||
)
|
||||
reader := strings.NewReader("helloword")
|
||||
|
||||
reads, _ = gfile.GetBinContentsTilChar(reader, 'w', 2)
|
||||
gtest.Assert(string(reads), "llow")
|
||||
|
||||
_, indexs = gfile.GetBinContentsTilChar(reader, 'w', 20)
|
||||
gtest.Assert(indexs, -1)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetBinContentsTilCharByPath(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
reads []byte
|
||||
indexs int64
|
||||
filepaths string = "/testfile_GetContents.txt"
|
||||
)
|
||||
|
||||
createTestFile(filepaths, "abcdefghijklmn")
|
||||
defer delTestFiles(filepaths)
|
||||
|
||||
reads, _ = gfile.GetBinContentsTilCharByPath(testpath()+filepaths, 'c', 2)
|
||||
gtest.Assert(string(reads), "c")
|
||||
|
||||
reads, _ = gfile.GetBinContentsTilCharByPath(testpath()+filepaths, 'y', 1)
|
||||
gtest.Assert(string(reads), "")
|
||||
|
||||
_, indexs = gfile.GetBinContentsTilCharByPath(testpath()+filepaths, 'x', 1)
|
||||
gtest.Assert(indexs, -1)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestHome(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
reads string
|
||||
err error
|
||||
)
|
||||
|
||||
reads, err = gfile.Home()
|
||||
gtest.Assert(err, nil)
|
||||
gtest.AssertNE(reads, "")
|
||||
|
||||
})
|
||||
}
|
||||
63
g/os/gfile/gfile_search_test.go
Normal file
63
g/os/gfile/gfile_search_test.go
Normal file
@ -0,0 +1,63 @@
|
||||
package gfile_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSearch(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths1 string = "/testfiless"
|
||||
paths2 string = "./testfile/dirfiles_no"
|
||||
tpath string
|
||||
tpath2 string
|
||||
tempstr string
|
||||
ypaths1 string
|
||||
err error
|
||||
)
|
||||
|
||||
createDir(paths1)
|
||||
defer delTestFiles(paths1)
|
||||
ypaths1 = paths1
|
||||
|
||||
tpath, err = gfile.Search(testpath() + paths1)
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
tpath = filepath.ToSlash(tpath)
|
||||
|
||||
// 自定义优先路径
|
||||
tpath2, err = gfile.Search(testpath() + paths1)
|
||||
gtest.Assert(err, nil)
|
||||
tpath2 = filepath.ToSlash(tpath2)
|
||||
|
||||
tempstr = testpath()
|
||||
paths1 = tempstr + paths1
|
||||
paths1 = filepath.ToSlash(paths1)
|
||||
|
||||
gtest.Assert(tpath, paths1)
|
||||
|
||||
gtest.Assert(tpath2, tpath)
|
||||
|
||||
// 测试给定目录
|
||||
tpath2, err = gfile.Search(paths1, "testfiless")
|
||||
tpath2 = filepath.ToSlash(tpath2)
|
||||
tempss := filepath.ToSlash(paths1)
|
||||
gtest.Assert(tpath2, tempss)
|
||||
|
||||
// 测试当前目录
|
||||
tempstr, _ = filepath.Abs("./")
|
||||
tempstr = testpath()
|
||||
paths1 = tempstr + ypaths1
|
||||
paths1 = filepath.ToSlash(paths1)
|
||||
|
||||
gtest.Assert(tpath2, paths1)
|
||||
|
||||
// 测试目录不存在时
|
||||
_, err = gfile.Search(paths2)
|
||||
gtest.AssertNE(err, nil)
|
||||
|
||||
})
|
||||
}
|
||||
59
g/os/gfile/gfile_size_test.go
Normal file
59
g/os/gfile/gfile_size_test.go
Normal file
@ -0,0 +1,59 @@
|
||||
package gfile_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSize(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths1 string = "/testfile_t1.txt"
|
||||
sizes int64
|
||||
)
|
||||
|
||||
createTestFile(paths1, "abcdefghijklmn")
|
||||
defer delTestFiles(paths1)
|
||||
|
||||
sizes = gfile.Size(testpath() + paths1)
|
||||
gtest.Assert(sizes, 14)
|
||||
|
||||
sizes = gfile.Size("")
|
||||
gtest.Assert(sizes, 0)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestFormatSize(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
gtest.Assert(gfile.FormatSize(0), "0.00B")
|
||||
gtest.Assert(gfile.FormatSize(16), "16.00B")
|
||||
|
||||
gtest.Assert(gfile.FormatSize(1024), "1.00K")
|
||||
|
||||
gtest.Assert(gfile.FormatSize(16000000), "15.26M")
|
||||
|
||||
gtest.Assert(gfile.FormatSize(1600000000), "1.49G")
|
||||
|
||||
gtest.Assert(gfile.FormatSize(9600000000000), "8.73T")
|
||||
gtest.Assert(gfile.FormatSize(9600000000000000), "8.53P")
|
||||
|
||||
gtest.Assert(gfile.FormatSize(9600000000000000000), "TooLarge")
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestReadableSize(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
|
||||
var (
|
||||
paths1 string = "/testfile_t1.txt"
|
||||
)
|
||||
createTestFile(paths1, "abcdefghijklmn")
|
||||
defer delTestFiles(paths1)
|
||||
gtest.Assert(gfile.ReadableSize(testpath()+paths1), "14.00B")
|
||||
gtest.Assert(gfile.ReadableSize(""), "0.00B")
|
||||
|
||||
})
|
||||
}
|
||||
686
g/os/gfile/gfile_test.go
Normal file
686
g/os/gfile/gfile_test.go
Normal file
@ -0,0 +1,686 @@
|
||||
package gfile_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIsDir(t *testing.T) {
|
||||
|
||||
gtest.Case(t, func() {
|
||||
paths := "/testfile"
|
||||
createDir(paths)
|
||||
defer delTestFiles(paths)
|
||||
|
||||
gtest.Assert(gfile.IsDir(testpath()+paths), true)
|
||||
gtest.Assert(gfile.IsDir("./testfile2"), false)
|
||||
gtest.Assert(gfile.IsDir("./testfile/tt.txt"), false)
|
||||
gtest.Assert(gfile.IsDir(""), false)
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
err error
|
||||
filepaths []string
|
||||
fileobj *os.File
|
||||
)
|
||||
|
||||
filepaths = append(filepaths, "/testfile_cc1.txt")
|
||||
filepaths = append(filepaths, "/testfile_cc2.txt")
|
||||
|
||||
for _, v := range filepaths {
|
||||
fileobj, err = gfile.Create(testpath() + v)
|
||||
defer delTestFiles(v)
|
||||
fileobj.Close()
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestOpen(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
err error
|
||||
files []string
|
||||
flags []bool
|
||||
fileobj *os.File
|
||||
)
|
||||
|
||||
file1 := "/testfile_nc1.txt"
|
||||
createTestFile(file1, "")
|
||||
defer delTestFiles(file1)
|
||||
|
||||
files = append(files, file1)
|
||||
flags = append(flags, true)
|
||||
|
||||
files = append(files, "./testfile/file1/c1.txt")
|
||||
flags = append(flags, false)
|
||||
|
||||
for k, v := range files {
|
||||
fileobj, err = gfile.Open(testpath() + v)
|
||||
fileobj.Close()
|
||||
if flags[k] {
|
||||
gtest.Assert(err, nil)
|
||||
} else {
|
||||
gtest.AssertNE(err, nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestOpenFile(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
err error
|
||||
files []string
|
||||
flags []bool
|
||||
fileobj *os.File
|
||||
)
|
||||
|
||||
files = append(files, "./testfile/file1/nc1.txt")
|
||||
flags = append(flags, false)
|
||||
|
||||
f1 := "/testfile_tt.txt"
|
||||
createTestFile(f1, "")
|
||||
defer delTestFiles(f1)
|
||||
|
||||
files = append(files, f1)
|
||||
flags = append(flags, true)
|
||||
|
||||
for k, v := range files {
|
||||
fileobj, err = gfile.OpenFile(testpath()+v, os.O_RDWR, 0666)
|
||||
fileobj.Close()
|
||||
if flags[k] {
|
||||
gtest.Assert(err, nil)
|
||||
} else {
|
||||
gtest.AssertNE(err, nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestOpenWithFlag(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
err error
|
||||
files []string
|
||||
flags []bool
|
||||
fileobj *os.File
|
||||
)
|
||||
|
||||
file1 := "/testfile_t1.txt"
|
||||
createTestFile(file1, "")
|
||||
defer delTestFiles(file1)
|
||||
files = append(files, file1)
|
||||
flags = append(flags, true)
|
||||
|
||||
files = append(files, "/testfiless/dirfiles/t1_no.txt")
|
||||
flags = append(flags, false)
|
||||
|
||||
for k, v := range files {
|
||||
fileobj, err = gfile.OpenWithFlag(testpath()+v, os.O_RDWR)
|
||||
fileobj.Close()
|
||||
if flags[k] {
|
||||
gtest.Assert(err, nil)
|
||||
} else {
|
||||
gtest.AssertNE(err, nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestOpenWithFlagPerm(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
err error
|
||||
files []string
|
||||
flags []bool
|
||||
fileobj *os.File
|
||||
)
|
||||
file1 := "/testfile_nc1.txt"
|
||||
createTestFile(file1, "")
|
||||
defer delTestFiles(file1)
|
||||
files = append(files, file1)
|
||||
flags = append(flags, true)
|
||||
|
||||
files = append(files, "/testfileyy/tt.txt")
|
||||
flags = append(flags, false)
|
||||
|
||||
for k, v := range files {
|
||||
fileobj, err = gfile.OpenWithFlagPerm(testpath()+v, os.O_RDWR, 666)
|
||||
fileobj.Close()
|
||||
if flags[k] {
|
||||
gtest.Assert(err, nil)
|
||||
} else {
|
||||
gtest.AssertNE(err, nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestExists(t *testing.T) {
|
||||
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
flag bool
|
||||
files []string
|
||||
flags []bool
|
||||
)
|
||||
|
||||
file1 := "/testfile_GetContents.txt"
|
||||
createTestFile(file1, "")
|
||||
defer delTestFiles(file1)
|
||||
|
||||
files = append(files, file1)
|
||||
flags = append(flags, true)
|
||||
|
||||
files = append(files, "./testfile/havefile1/tt_no.txt")
|
||||
flags = append(flags, false)
|
||||
|
||||
for k, v := range files {
|
||||
flag = gfile.Exists(testpath() + v)
|
||||
if flags[k] {
|
||||
gtest.Assert(flag, true)
|
||||
} else {
|
||||
gtest.Assert(flag, false)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestPwd(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
paths, err := os.Getwd()
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(gfile.Pwd(), paths)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestIsFile(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
flag bool
|
||||
files []string
|
||||
flags []bool
|
||||
)
|
||||
|
||||
file1 := "/testfile_tt.txt"
|
||||
createTestFile(file1, "")
|
||||
defer delTestFiles(file1)
|
||||
files = append(files, file1)
|
||||
flags = append(flags, true)
|
||||
|
||||
dir1 := "/testfiless"
|
||||
createDir(dir1)
|
||||
defer delTestFiles(dir1)
|
||||
files = append(files, dir1)
|
||||
flags = append(flags, false)
|
||||
|
||||
files = append(files, "./testfiledd/tt1.txt")
|
||||
flags = append(flags, false)
|
||||
|
||||
for k, v := range files {
|
||||
flag = gfile.IsFile(testpath() + v)
|
||||
if flags[k] {
|
||||
gtest.Assert(flag, true)
|
||||
} else {
|
||||
gtest.Assert(flag, false)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestInfo(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
err error
|
||||
paths string = "/testfile_t1.txt"
|
||||
files os.FileInfo
|
||||
files2 os.FileInfo
|
||||
)
|
||||
|
||||
createTestFile(paths, "")
|
||||
defer delTestFiles(paths)
|
||||
files, err = gfile.Info(testpath() + paths)
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
files2, err = os.Stat(testpath() + paths)
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
gtest.Assert(files, files2)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestMove(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths string = "/ovetest"
|
||||
filepaths string = "/testfile_ttn1.txt"
|
||||
topath string = "/testfile_ttn2.txt"
|
||||
)
|
||||
createDir("/ovetest")
|
||||
createTestFile(paths+filepaths, "a")
|
||||
|
||||
defer delTestFiles(paths)
|
||||
|
||||
yfile := testpath() + paths + filepaths
|
||||
tofile := testpath() + paths + topath
|
||||
|
||||
gtest.Assert(gfile.Move(yfile, tofile), nil)
|
||||
|
||||
// 检查移动后的文件是否真实存在
|
||||
_, err := os.Stat(tofile)
|
||||
gtest.Assert(os.IsNotExist(err), false)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestRename(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths string = "/testfiles"
|
||||
ypath string = "/testfilettm1.txt"
|
||||
topath string = "/testfilettm2.txt"
|
||||
)
|
||||
createDir(paths)
|
||||
createTestFile(paths+ypath, "a")
|
||||
defer delTestFiles(paths)
|
||||
|
||||
ypath = testpath() + paths + ypath
|
||||
topath = testpath() + paths + topath
|
||||
|
||||
gtest.Assert(gfile.Rename(ypath, topath), nil)
|
||||
gtest.Assert(gfile.IsFile(topath), true)
|
||||
|
||||
gtest.AssertNE(gfile.Rename("", ""), nil)
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestCopy(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths string = "/testfile_copyfile1.txt"
|
||||
topath string = "/testfile_copyfile2.txt"
|
||||
)
|
||||
|
||||
createTestFile(paths, "")
|
||||
defer delTestFiles(paths)
|
||||
|
||||
gtest.Assert(gfile.Copy(testpath()+paths, testpath()+topath), nil)
|
||||
defer delTestFiles(topath)
|
||||
|
||||
gtest.Assert(gfile.IsFile(testpath()+topath), true)
|
||||
|
||||
gtest.AssertNE(gfile.Copy("", ""), nil)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestDirNames(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths string = "/testdirs"
|
||||
err error
|
||||
readlist []string
|
||||
)
|
||||
havelist := []string{
|
||||
"t1.txt",
|
||||
"t2.txt",
|
||||
}
|
||||
|
||||
// 创建测试文件
|
||||
createDir(paths)
|
||||
for _, v := range havelist {
|
||||
createTestFile(paths+"/"+v, "")
|
||||
}
|
||||
defer delTestFiles(paths)
|
||||
|
||||
readlist, err = gfile.DirNames(testpath() + paths)
|
||||
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(havelist, readlist)
|
||||
|
||||
_, err = gfile.DirNames("")
|
||||
gtest.AssertNE(err, nil)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestGlob(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths string = "/testfiles/*.txt"
|
||||
dirpath string = "/testfiles"
|
||||
err error
|
||||
resultlist []string
|
||||
)
|
||||
|
||||
havelist1 := []string{
|
||||
"t1.txt",
|
||||
"t2.txt",
|
||||
}
|
||||
|
||||
havelist2 := []string{
|
||||
testpath() + "/testfiles/t1.txt",
|
||||
testpath() + "/testfiles/t2.txt",
|
||||
}
|
||||
|
||||
//===============================构建测试文件
|
||||
createDir(dirpath)
|
||||
for _, v := range havelist1 {
|
||||
createTestFile(dirpath+"/"+v, "")
|
||||
}
|
||||
defer delTestFiles(dirpath)
|
||||
|
||||
resultlist, err = gfile.Glob(testpath()+paths, true)
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(resultlist, havelist1)
|
||||
|
||||
resultlist, err = gfile.Glob(testpath()+paths, false)
|
||||
|
||||
gtest.Assert(err, nil)
|
||||
gtest.Assert(formatpaths(resultlist), formatpaths(havelist2))
|
||||
|
||||
_, err = gfile.Glob("", true)
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestRemove(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths string = "/testfile_t1.txt"
|
||||
)
|
||||
createTestFile(paths, "")
|
||||
gtest.Assert(gfile.Remove(testpath()+paths), nil)
|
||||
|
||||
gtest.Assert(gfile.Remove(""), nil)
|
||||
|
||||
defer delTestFiles(paths)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestIsReadable(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths1 string = "/testfile_GetContents.txt"
|
||||
paths2 string = "./testfile_GetContents_no.txt"
|
||||
)
|
||||
|
||||
createTestFile(paths1, "")
|
||||
defer delTestFiles(paths1)
|
||||
|
||||
gtest.Assert(gfile.IsReadable(testpath()+paths1), true)
|
||||
gtest.Assert(gfile.IsReadable(paths2), false)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestIsWritable(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths1 string = "/testfile_GetContents.txt"
|
||||
paths2 string = "./testfile_GetContents_no.txt"
|
||||
)
|
||||
|
||||
createTestFile(paths1, "")
|
||||
defer delTestFiles(paths1)
|
||||
gtest.Assert(gfile.IsWritable(testpath()+paths1), true)
|
||||
gtest.Assert(gfile.IsWritable(paths2), false)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestChmod(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths1 string = "/testfile_GetContents.txt"
|
||||
paths2 string = "./testfile_GetContents_no.txt"
|
||||
)
|
||||
createTestFile(paths1, "")
|
||||
defer delTestFiles(paths1)
|
||||
|
||||
gtest.Assert(gfile.Chmod(testpath()+paths1, 0777), nil)
|
||||
gtest.AssertNE(gfile.Chmod(paths2, 0777), nil)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestScanDir(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths1 string = "/testfiledirs"
|
||||
files []string
|
||||
err error
|
||||
)
|
||||
|
||||
createDir(paths1)
|
||||
createTestFile(paths1+"/t1.txt", "")
|
||||
createTestFile(paths1+"/t2.txt", "")
|
||||
defer delTestFiles(paths1)
|
||||
|
||||
files, err = gfile.ScanDir(testpath()+paths1, "t*")
|
||||
|
||||
result := []string{
|
||||
testpath() + paths1 + "/t1.txt",
|
||||
testpath() + paths1 + "/t2.txt",
|
||||
}
|
||||
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
gtest.Assert(formatpaths(files), formatpaths(result))
|
||||
|
||||
_, err = gfile.ScanDir("", "t*")
|
||||
gtest.AssertNE(err, nil)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// 获取绝对目录地址
|
||||
func TestRealPath(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths1 string = "/testfile_files"
|
||||
readlPath string
|
||||
|
||||
tempstr string
|
||||
)
|
||||
|
||||
createDir(paths1)
|
||||
defer delTestFiles(paths1)
|
||||
|
||||
readlPath = gfile.RealPath("./")
|
||||
|
||||
tempstr, _ = filepath.Abs("./")
|
||||
|
||||
gtest.Assert(readlPath, tempstr)
|
||||
|
||||
gtest.Assert(gfile.RealPath("./nodirs"), "")
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// 获取当前执行文件的目录
|
||||
func TestSelfPath(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths1 string
|
||||
readlPath string
|
||||
tempstr string
|
||||
)
|
||||
readlPath = gfile.SelfPath()
|
||||
readlPath = filepath.ToSlash(readlPath)
|
||||
|
||||
tempstr, _ = filepath.Abs(os.Args[0])
|
||||
paths1 = filepath.ToSlash(tempstr)
|
||||
paths1 = strings.Replace(paths1, "./", "/", 1)
|
||||
|
||||
gtest.Assert(readlPath, paths1)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestSelfDir(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths1 string
|
||||
readlPath string
|
||||
tempstr string
|
||||
)
|
||||
readlPath = gfile.SelfDir()
|
||||
|
||||
tempstr, _ = filepath.Abs(os.Args[0])
|
||||
paths1 = filepath.Dir(tempstr)
|
||||
|
||||
gtest.Assert(readlPath, paths1)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestBasename(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths1 string = "/testfilerr_GetContents.txt"
|
||||
readlPath string
|
||||
)
|
||||
|
||||
createTestFile(paths1, "")
|
||||
defer delTestFiles(paths1)
|
||||
|
||||
readlPath = gfile.Basename(testpath() + paths1)
|
||||
gtest.Assert(readlPath, "testfilerr_GetContents.txt")
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestDir(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths1 string = "/testfiless"
|
||||
readlPath string
|
||||
)
|
||||
createDir(paths1)
|
||||
defer delTestFiles(paths1)
|
||||
|
||||
readlPath = gfile.Dir(testpath() + paths1)
|
||||
|
||||
gtest.Assert(readlPath, testpath())
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// 获取文件名
|
||||
func TestExt(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
paths1 string = "/testfile_GetContents.txt"
|
||||
dirpath1 = "/testdirs"
|
||||
)
|
||||
createTestFile(paths1, "")
|
||||
defer delTestFiles(paths1)
|
||||
|
||||
createDir(dirpath1)
|
||||
defer delTestFiles(dirpath1)
|
||||
|
||||
gtest.Assert(gfile.Ext(testpath()+paths1), ".txt")
|
||||
gtest.Assert(gfile.Ext(testpath()+dirpath1), "")
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestTempDir(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
tpath string
|
||||
)
|
||||
|
||||
tpath = gfile.TempDir()
|
||||
gtest.Assert(tpath, os.TempDir())
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestMkdir(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
tpath string = "/testfile/createdir"
|
||||
err error
|
||||
)
|
||||
|
||||
defer delTestFiles("/testfile")
|
||||
|
||||
err = gfile.Mkdir(testpath() + tpath)
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
err = gfile.Mkdir("")
|
||||
gtest.AssertNE(err, nil)
|
||||
|
||||
err = gfile.Mkdir(testpath() + tpath + "2/t1")
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestStat(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
tpath1 string = "/testfile_t1.txt"
|
||||
tpath2 string = "./testfile_t1_no.txt"
|
||||
err error
|
||||
fileiofo os.FileInfo
|
||||
)
|
||||
|
||||
createTestFile(tpath1, "a")
|
||||
defer delTestFiles(tpath1)
|
||||
|
||||
fileiofo, err = gfile.Stat(testpath() + tpath1)
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
gtest.Assert(fileiofo.Size(), 1)
|
||||
|
||||
_, err = gfile.Stat(tpath2)
|
||||
gtest.AssertNE(err, nil)
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
func TestMainPkgPath(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
reads string
|
||||
)
|
||||
|
||||
reads = gfile.MainPkgPath()
|
||||
gtest.Assert(reads, "")
|
||||
|
||||
})
|
||||
}
|
||||
45
g/os/gfile/gfile_time_test.go
Normal file
45
g/os/gfile/gfile_time_test.go
Normal file
@ -0,0 +1,45 @@
|
||||
package gfile_test
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMTime(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
|
||||
var (
|
||||
file1 string = "/testfile_t1.txt"
|
||||
err error
|
||||
fileobj os.FileInfo
|
||||
)
|
||||
|
||||
createTestFile(file1, "")
|
||||
defer delTestFiles(file1)
|
||||
fileobj, err = os.Stat(testpath() + file1)
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
gtest.Assert(gfile.MTime(testpath()+file1), fileobj.ModTime().Unix())
|
||||
gtest.Assert(gfile.MTime(""), 0)
|
||||
})
|
||||
}
|
||||
|
||||
func TestMTimeMillisecond(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
var (
|
||||
file1 string = "/testfile_t1.txt"
|
||||
err error
|
||||
fileobj os.FileInfo
|
||||
)
|
||||
|
||||
createTestFile(file1, "")
|
||||
defer delTestFiles(file1)
|
||||
fileobj, err = os.Stat(testpath() + file1)
|
||||
gtest.Assert(err, nil)
|
||||
|
||||
gtest.AssertGTE(gfile.MTimeMillisecond(testpath()+file1), fileobj.ModTime().Nanosecond()/1000000)
|
||||
gtest.Assert(gfile.MTimeMillisecond(""), 0)
|
||||
})
|
||||
}
|
||||
@ -29,7 +29,6 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// 视图对象
|
||||
type View struct {
|
||||
mu sync.RWMutex
|
||||
paths *garray.StringArray // 模板查找目录(绝对路径)
|
||||
@ -38,29 +37,32 @@ type View struct {
|
||||
delimiters []string // 模板变量分隔符号
|
||||
}
|
||||
|
||||
// 模板变量
|
||||
// Template params type.
|
||||
type Params = map[string]interface{}
|
||||
|
||||
// 函数映射表
|
||||
// Customized template function map type.
|
||||
type FuncMap = map[string]interface{}
|
||||
|
||||
// 默认的视图对象
|
||||
// Default view object.
|
||||
var defaultViewObj *View
|
||||
|
||||
// 初始化默认的视图对象, 默认加载包不会初始化,使用包方法才会初始化模板引擎对象。
|
||||
// checkAndInitDefaultView checks and initializes the default view object.
|
||||
// The default view object will be initialized just once.
|
||||
func checkAndInitDefaultView() {
|
||||
if defaultViewObj == nil {
|
||||
defaultViewObj = New(gfile.Pwd())
|
||||
}
|
||||
}
|
||||
|
||||
// 直接解析模板内容,返回解析后的内容
|
||||
// ParseContent parses the template content directly using the default view object
|
||||
// and returns the parsed content.
|
||||
func ParseContent(content string, params Params) ([]byte, error) {
|
||||
checkAndInitDefaultView()
|
||||
return defaultViewObj.ParseContent(content, params)
|
||||
}
|
||||
|
||||
// 生成一个视图对象
|
||||
// New returns a new view object.
|
||||
// The parameter <path> specifies the template directory path to load template files.
|
||||
func New(path...string) *View {
|
||||
view := &View {
|
||||
paths : garray.NewStringArray(),
|
||||
@ -92,11 +94,11 @@ func New(path...string) *View {
|
||||
}
|
||||
}
|
||||
view.SetDelimiters("{{", "}}")
|
||||
// 内置变量
|
||||
// default build-in variables.
|
||||
view.data["GF"] = map[string]interface{} {
|
||||
"version" : gf.VERSION,
|
||||
}
|
||||
// 内置方法
|
||||
// default build-in functions.
|
||||
view.BindFunc("text", view.funcText)
|
||||
view.BindFunc("html", view.funcHtmlEncode)
|
||||
view.BindFunc("htmlencode", view.funcHtmlEncode)
|
||||
@ -117,12 +119,13 @@ func New(path...string) *View {
|
||||
return view
|
||||
}
|
||||
|
||||
// 设置模板目录绝对路径
|
||||
// SetPath sets the template directory path for template file search.
|
||||
// The param <path> can be absolute or relative path, but absolute path is suggested.
|
||||
func (view *View) SetPath(path string) error {
|
||||
// 判断绝对路径(或者工作目录下目录)
|
||||
// Absolute path.
|
||||
realPath := gfile.RealPath(path)
|
||||
if realPath == "" {
|
||||
// 判断相对路径
|
||||
// Relative path.
|
||||
view.paths.RLockFunc(func(array []string) {
|
||||
for _, v := range array {
|
||||
if path, _ := gspath.Search(v, path); path != "" {
|
||||
@ -132,7 +135,7 @@ func (view *View) SetPath(path string) error {
|
||||
}
|
||||
})
|
||||
}
|
||||
// 目录不存在错误处理
|
||||
// Path not exist.
|
||||
if realPath == "" {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
if view.paths.Len() > 0 {
|
||||
@ -149,13 +152,13 @@ func (view *View) SetPath(path string) error {
|
||||
glog.Error(err)
|
||||
return err
|
||||
}
|
||||
// 路径必须为目录类型
|
||||
// Should be a directory.
|
||||
if !gfile.IsDir(realPath) {
|
||||
err := errors.New(fmt.Sprintf(`[gview] SetPath failed: path "%s" should be directory type`, path))
|
||||
glog.Error(err)
|
||||
return err
|
||||
}
|
||||
// 重复判断
|
||||
// Repeated path check.
|
||||
if view.paths.Search(realPath) != -1 {
|
||||
return nil
|
||||
}
|
||||
@ -165,12 +168,12 @@ func (view *View) SetPath(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 添加模板目录搜索路径
|
||||
// AddPath adds a absolute or relative path to the search paths.
|
||||
func (view *View) AddPath(path string) error {
|
||||
// 判断绝对路径(或者工作目录下目录)
|
||||
// Absolute path.
|
||||
realPath := gfile.RealPath(path)
|
||||
if realPath == "" {
|
||||
// 判断相对路径
|
||||
// Relative path.
|
||||
view.paths.RLockFunc(func(array []string) {
|
||||
for _, v := range array {
|
||||
if path, _ := gspath.Search(v, path); path != "" {
|
||||
@ -180,7 +183,7 @@ func (view *View) AddPath(path string) error {
|
||||
}
|
||||
})
|
||||
}
|
||||
// 目录不存在错误处理
|
||||
// Path not exist.
|
||||
if realPath == "" {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
if view.paths.Len() > 0 {
|
||||
@ -197,13 +200,13 @@ func (view *View) AddPath(path string) error {
|
||||
glog.Error(err)
|
||||
return err
|
||||
}
|
||||
// 路径必须为目录类型
|
||||
// realPath should be type of folder.
|
||||
if !gfile.IsDir(realPath) {
|
||||
err := errors.New(fmt.Sprintf(`[gview] AddPath failed: path "%s" should be directory type`, path))
|
||||
glog.Error(err)
|
||||
return err
|
||||
}
|
||||
// 重复判断
|
||||
// Repeated path check.
|
||||
if view.paths.Search(realPath) != -1 {
|
||||
return nil
|
||||
}
|
||||
@ -212,7 +215,8 @@ func (view *View) AddPath(path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 批量绑定模板变量,即调用之后每个线程都会生效,因此有并发安全控制
|
||||
// Assign binds multiple template variables to current view object.
|
||||
// Each goroutine will take effect after the call, so it is concurrent-safe.
|
||||
func (view *View) Assigns(data Params) {
|
||||
view.mu.Lock()
|
||||
for k, v := range data {
|
||||
@ -221,15 +225,18 @@ func (view *View) Assigns(data Params) {
|
||||
view.mu.Unlock()
|
||||
}
|
||||
|
||||
// 绑定模板变量,即调用之后每个线程都会生效,因此有并发安全控制
|
||||
// Assign binds a template variable to current view object.
|
||||
// Each goroutine will take effect after the call, so it is concurrent-safe.
|
||||
func (view *View) Assign(key string, value interface{}) {
|
||||
view.mu.Lock()
|
||||
view.data[key] = value
|
||||
view.mu.Unlock()
|
||||
}
|
||||
|
||||
// 解析模板,返回解析后的内容
|
||||
func (view *View) Parse(file string, params Params, funcmap...map[string]interface{}) ([]byte, error) {
|
||||
// ParseContent parses given template file <file>
|
||||
// with given template parameters <params> and function map <funcMap>
|
||||
// and returns the parsed content in []byte.
|
||||
func (view *View) Parse(file string, params Params, funcMap...map[string]interface{}) ([]byte, error) {
|
||||
path := ""
|
||||
view.paths.RLockFunc(func(array []string) {
|
||||
for _, v := range array {
|
||||
@ -254,19 +261,19 @@ func (view *View) Parse(file string, params Params, funcmap...map[string]interfa
|
||||
return nil, errors.New(fmt.Sprintf(`tpl "%s" not found`, file))
|
||||
}
|
||||
content := gfcache.GetContents(path)
|
||||
// 执行模板解析,互斥锁主要是用于funcmap
|
||||
view.mu.RLock()
|
||||
defer view.mu.RUnlock()
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
tplobj := template.New(path).Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcmap)
|
||||
if len(funcmap) > 0 {
|
||||
tplobj = tplobj.Funcs(funcmap[0])
|
||||
tplObj := template.New(path).Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcmap)
|
||||
if len(funcMap) > 0 {
|
||||
tplObj = tplObj.Funcs(funcMap[0])
|
||||
}
|
||||
if tpl, err := tplobj.Parse(content); err != nil {
|
||||
if tpl, err := tplObj.Parse(content); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
// 注意模板变量赋值不能改变已有的params或者view.data的值,因为这两个变量都是指针
|
||||
// 因此在必要条件下,需要合并两个map的值到一个新的map
|
||||
// Note that the template variable assignment cannot change the value
|
||||
// of the existing <params> or view.data because both variables are pointers.
|
||||
// It's need to merge the values of the two maps into a new map.
|
||||
vars := (map[string]interface{})(nil)
|
||||
if len(view.data) > 0 {
|
||||
if len(params) > 0 {
|
||||
@ -290,21 +297,24 @@ func (view *View) Parse(file string, params Params, funcmap...map[string]interfa
|
||||
return buffer.Bytes(), nil
|
||||
}
|
||||
|
||||
// 直接解析模板内容,返回解析后的内容
|
||||
func (view *View) ParseContent(content string, params Params, funcmap...map[string]interface{}) ([]byte, error) {
|
||||
// ParseContent parses given template content <content>
|
||||
// with given template parameters <params> and function map <funcMap>
|
||||
// and returns the parsed content in []byte.
|
||||
func (view *View) ParseContent(content string, params Params, funcMap...map[string]interface{}) ([]byte, error) {
|
||||
view.mu.RLock()
|
||||
defer view.mu.RUnlock()
|
||||
name := gconv.String(ghash.BKDRHash64([]byte(content)))
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
tplobj := template.New(name).Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcmap)
|
||||
if len(funcmap) > 0 {
|
||||
tplobj = tplobj.Funcs(funcmap[0])
|
||||
tplObj := template.New(name).Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcmap)
|
||||
if len(funcMap) > 0 {
|
||||
tplObj = tplObj.Funcs(funcMap[0])
|
||||
}
|
||||
if tpl, err := tplobj.Parse(content); err != nil {
|
||||
if tpl, err := tplObj.Parse(content); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
// 注意模板变量赋值不能改变已有的params或者view.data的值,因为这两个变量都是指针
|
||||
// 因此在必要条件下,需要合并两个map的值到一个新的map
|
||||
// Note that the template variable assignment cannot change the value
|
||||
// of the existing <params> or view.data because both variables are pointers.
|
||||
// It's need to merge the values of the two maps into a new map.
|
||||
vars := (map[string]interface{})(nil)
|
||||
if len(view.data) > 0 {
|
||||
if len(params) > 0 {
|
||||
@ -328,20 +338,33 @@ func (view *View) ParseContent(content string, params Params, funcmap...map[stri
|
||||
return buffer.Bytes(), nil
|
||||
}
|
||||
|
||||
// 设置模板变量解析分隔符号
|
||||
// SetDelimiters sets customized delimiters for template parsing.
|
||||
func (view *View) SetDelimiters(left, right string) {
|
||||
view.delimiters[0] = left
|
||||
view.delimiters[1] = right
|
||||
}
|
||||
|
||||
// 绑定自定义函数,该函数是全局有效,即调用之后每个线程都会生效,因此有并发安全控制
|
||||
// BindFunc registers customized template function named <name>
|
||||
// with given function <function> to current view object.
|
||||
// The <name> is the function name which can be called in template content.
|
||||
func (view *View) BindFunc(name string, function interface{}) {
|
||||
view.mu.Lock()
|
||||
view.funcmap[name] = function
|
||||
view.mu.Unlock()
|
||||
}
|
||||
|
||||
// 模板内置方法:include
|
||||
// BindFuncMap registers customized template functions by map to current view object.
|
||||
// The key of map is the template function name
|
||||
// and the value of map is the address of customized function.
|
||||
func (view *View) BindFuncMap(funcMap FuncMap) {
|
||||
view.mu.Lock()
|
||||
for k, v := range funcMap {
|
||||
view.funcmap[k] = v
|
||||
}
|
||||
view.mu.Unlock()
|
||||
}
|
||||
|
||||
// Build-in template function: include
|
||||
func (view *View) funcInclude(file string, data...map[string]interface{}) string {
|
||||
var m map[string]interface{} = nil
|
||||
if len(data) > 0 {
|
||||
@ -354,27 +377,27 @@ func (view *View) funcInclude(file string, data...map[string]interface{}) string
|
||||
return string(content)
|
||||
}
|
||||
|
||||
// 模板内置方法:text
|
||||
// Build-in template function: text
|
||||
func (view *View) funcText(html interface{}) string {
|
||||
return ghtml.StripTags(gconv.String(html))
|
||||
}
|
||||
|
||||
// 模板内置方法:html
|
||||
// Build-in template function: html
|
||||
func (view *View) funcHtmlEncode(html interface{}) string {
|
||||
return ghtml.Entities(gconv.String(html))
|
||||
}
|
||||
|
||||
// 模板内置方法:htmldecode
|
||||
// Build-in template function: htmldecode
|
||||
func (view *View) funcHtmlDecode(html interface{}) string {
|
||||
return ghtml.EntitiesDecode(gconv.String(html))
|
||||
}
|
||||
|
||||
// 模板内置方法:url
|
||||
// Build-in template function: url
|
||||
func (view *View) funcUrlEncode(url interface{}) string {
|
||||
return gurl.Encode(gconv.String(url))
|
||||
}
|
||||
|
||||
// 模板内置方法:urldecode
|
||||
// Build-in template function: urldecode
|
||||
func (view *View) funcUrlDecode(url interface{}) string {
|
||||
if content, err := gurl.Decode(gconv.String(url)); err == nil {
|
||||
return content
|
||||
@ -383,7 +406,7 @@ func (view *View) funcUrlDecode(url interface{}) string {
|
||||
}
|
||||
}
|
||||
|
||||
// 模板内置方法:date
|
||||
// Build-in template function: date
|
||||
func (view *View) funcDate(format string, timestamp...interface{}) string {
|
||||
t := int64(0)
|
||||
if len(timestamp) > 0 {
|
||||
@ -395,42 +418,42 @@ func (view *View) funcDate(format string, timestamp...interface{}) string {
|
||||
return gtime.NewFromTimeStamp(t).Format(format)
|
||||
}
|
||||
|
||||
// 模板内置方法:compare
|
||||
// Build-in template function: compare
|
||||
func (view *View) funcCompare(value1, value2 interface{}) int {
|
||||
return strings.Compare(gconv.String(value1), gconv.String(value2))
|
||||
}
|
||||
|
||||
// 模板内置方法:substr
|
||||
// Build-in template function: substr
|
||||
func (view *View) funcSubStr(start, end int, str interface{}) string {
|
||||
return gstr.SubStr(gconv.String(str), start, end)
|
||||
}
|
||||
|
||||
// 模板内置方法:strlimit
|
||||
// Build-in template function: strlimit
|
||||
func (view *View) funcStrLimit(length int, suffix string, str interface{}) string {
|
||||
return gstr.StrLimit(gconv.String(str), length, suffix)
|
||||
}
|
||||
|
||||
// 模板内置方法:highlight
|
||||
// Build-in template function: highlight
|
||||
func (view *View) funcHighlight(key string, color string, str interface{}) string {
|
||||
return gstr.Replace(gconv.String(str), key, fmt.Sprintf(`<span style="color:%s;">%s</span>`, color, key))
|
||||
}
|
||||
|
||||
// 模板内置方法:hidestr
|
||||
// Build-in template function: hidestr
|
||||
func (view *View) funcHideStr(percent int, hide string, str interface{}) string {
|
||||
return gstr.HideStr(gconv.String(str), percent, hide)
|
||||
}
|
||||
|
||||
// 模板内置方法:toupper
|
||||
// Build-in template function: toupper
|
||||
func (view *View) funcToUpper(str interface{}) string {
|
||||
return gstr.ToUpper(gconv.String(str))
|
||||
}
|
||||
|
||||
// 模板内置方法:toupper
|
||||
// Build-in template function: toupper
|
||||
func (view *View) funcToLower(str interface{}) string {
|
||||
return gstr.ToLower(gconv.String(str))
|
||||
}
|
||||
|
||||
// 模板内置方法:nl2br
|
||||
// Build-in template function: nl2br
|
||||
func (view *View) funcNl2Br(str interface{}) string {
|
||||
return gstr.Nl2Br(gconv.String(str))
|
||||
}
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/os/gview"
|
||||
)
|
||||
|
||||
// 用于测试的内置函数
|
||||
func funcTest() string {
|
||||
return "test"
|
||||
}
|
||||
|
||||
func main() {
|
||||
view := g.View()
|
||||
b, err := view.Parse("index.html", nil, gview.FuncMap{
|
||||
"test": funcTest,
|
||||
})
|
||||
fmt.Println(err)
|
||||
fmt.Println(string(b))
|
||||
}
|
||||
23
geg/os/gview/bind_func/gview_func1.go
Normal file
23
geg/os/gview/bind_func/gview_func1.go
Normal file
@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/os/gview"
|
||||
)
|
||||
|
||||
// 用于测试的内置函数
|
||||
func funcTest() string {
|
||||
return "test content"
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 解析模板的时候传递模板函数映射Map,仅会在当前模板解析生效
|
||||
parsed, err := g.View().ParseContent(`call build-in function test: {{test}}`, nil, gview.FuncMap {
|
||||
"test": funcTest,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(string(parsed))
|
||||
}
|
||||
31
geg/os/gview/bind_func/gview_func2.go
Normal file
31
geg/os/gview/bind_func/gview_func2.go
Normal file
@ -0,0 +1,31 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
)
|
||||
|
||||
// 用于测试的带参数的内置函数
|
||||
func funcHello(name string) string {
|
||||
return fmt.Sprintf(`Hello %s`, name)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// 绑定全局的模板函数
|
||||
g.View().BindFunc("hello", funcHello)
|
||||
|
||||
// 普通方式传参
|
||||
parsed1, err := g.View().ParseContent(`{{hello "GoFrame"}}`, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(string(parsed1))
|
||||
|
||||
// 通过管道传参
|
||||
parsed2, err := g.View().ParseContent(`{{"GoFrame" | hello}}`, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(string(parsed2))
|
||||
}
|
||||
|
||||
@ -2,14 +2,21 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g/util/grand"
|
||||
"github.com/gogf/gf/g/container/gtype"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
)
|
||||
|
||||
|
||||
|
||||
func main() {
|
||||
for {
|
||||
fmt.Println(grand.Intn(100))
|
||||
}
|
||||
|
||||
var add float32
|
||||
add = 3.1415926
|
||||
|
||||
myF32 := gtype.NewFloat32(add)
|
||||
myAdd := myF32.Add(float32(6.2951413))
|
||||
|
||||
add += float32(6.2951413)
|
||||
|
||||
fmt.Println(myF32.Val())
|
||||
gtest.AssertEQ(myAdd, add)
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user