mirror of
https://github.com/acepanel/panel.git
synced 2026-02-04 13:47:15 +08:00
feat: add tests
This commit is contained in:
42
packages/captcha/captcha_test.go
Normal file
42
packages/captcha/captcha_test.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package captcha
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
testifymock "github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/goravel/framework/testing/mock"
|
||||
)
|
||||
|
||||
type CaptchaTestSuite struct {
|
||||
suite.Suite
|
||||
captcha *Captcha
|
||||
}
|
||||
|
||||
func TestCaptchaTestSuite(t *testing.T) {
|
||||
mockConfig := mock.Config()
|
||||
mockConfig.On("GetString", "app.name").Return("HaoZiPanel").Once()
|
||||
mockConfig.On("GetInt", "captcha.height").Return(80).Once()
|
||||
mockConfig.On("GetInt", "captcha.width").Return(240).Once()
|
||||
mockConfig.On("GetInt", "captcha.length").Return(4).Once()
|
||||
mockConfig.On("Get", "captcha.maxskew").Return(0.7).Once()
|
||||
mockConfig.On("GetInt", "captcha.dotcount").Return(80).Once()
|
||||
mockConfig.On("GetInt", "captcha.expire_time").Return(5).Once()
|
||||
mockConfig.On("GetInt", "captcha.debug_expire_time").Return(10).Once()
|
||||
mockConfig.On("GetBool", "app.debug").Return(true).Once()
|
||||
mockCache, _, _ := mock.Cache()
|
||||
mockCache.On("Put", testifymock.Anything, testifymock.Anything, time.Minute*time.Duration(10)).Return(nil).Once()
|
||||
suite.Run(t, &CaptchaTestSuite{
|
||||
captcha: NewCaptcha(),
|
||||
})
|
||||
mockConfig.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func (s *CaptchaTestSuite) TestGenerateCaptcha() {
|
||||
id, base64, err := s.captcha.GenerateCaptcha()
|
||||
s.NotEmpty(id)
|
||||
s.NotEmpty(base64)
|
||||
s.Nil(err)
|
||||
}
|
||||
@@ -2,15 +2,8 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/shirou/gopsutil/cpu"
|
||||
"github.com/shirou/gopsutil/disk"
|
||||
@@ -18,94 +11,8 @@ import (
|
||||
"github.com/shirou/gopsutil/load"
|
||||
"github.com/shirou/gopsutil/mem"
|
||||
"github.com/shirou/gopsutil/net"
|
||||
"github.com/shirou/gopsutil/process"
|
||||
)
|
||||
|
||||
// Empty 类似于 PHP 的 empty() 函数
|
||||
func Empty(val interface{}) bool {
|
||||
if val == nil {
|
||||
return true
|
||||
}
|
||||
v := reflect.ValueOf(val)
|
||||
switch v.Kind() {
|
||||
case reflect.String, reflect.Array:
|
||||
return v.Len() == 0
|
||||
case reflect.Map, reflect.Slice:
|
||||
return v.Len() == 0 || v.IsNil()
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
return v.IsNil()
|
||||
}
|
||||
return reflect.DeepEqual(val, reflect.Zero(v.Type()).Interface())
|
||||
}
|
||||
|
||||
// FirstElement 安全地获取 args[0],避免 panic: runtime error: index out of range
|
||||
func FirstElement(args []string) string {
|
||||
if len(args) > 0 {
|
||||
return args[0]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// RandomNumber 生成长度为 length 随机数字字符串
|
||||
func RandomNumber(length int) string {
|
||||
table := [...]byte{'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}
|
||||
b := make([]byte, length)
|
||||
n, err := io.ReadAtLeast(rand.Reader, b, length)
|
||||
if n != length {
|
||||
panic(err)
|
||||
}
|
||||
for i := 0; i < len(b); i++ {
|
||||
b[i] = table[int(b[i])%len(table)]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// RandomString 生成长度为 length 的随机字符串
|
||||
func RandomString(length int) string {
|
||||
b := make([]byte, length)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
letters := "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
for i, v := range b {
|
||||
b[i] = letters[v%byte(len(letters))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// MD5 生成字符串的 MD5 值
|
||||
func MD5(str string) string {
|
||||
return fmt.Sprintf("%x", md5.Sum([]byte(str)))
|
||||
}
|
||||
|
||||
// FormatBytes 格式化bytes
|
||||
func FormatBytes(size float64) string {
|
||||
units := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
|
||||
|
||||
i := 0
|
||||
for ; size >= 1024 && i < len(units); i++ {
|
||||
size /= 1024
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%.2f %s", size, units[i])
|
||||
}
|
||||
|
||||
// Cut 裁剪字符串
|
||||
func Cut(begin, end, str string) string {
|
||||
b := utf8.RuneCountInString(str[:strings.Index(str, begin)]) + utf8.RuneCountInString(begin)
|
||||
e := utf8.RuneCountInString(str[:strings.Index(str, end)]) - b
|
||||
return string([]rune(str)[b : b+e])
|
||||
}
|
||||
|
||||
// MonitoringInfo 监控信息
|
||||
type MonitoringInfo struct {
|
||||
Cpus []cpu.InfoStat `json:"cpus"`
|
||||
@@ -118,7 +25,6 @@ type MonitoringInfo struct {
|
||||
DiskIO map[string]disk.IOCountersStat `json:"disk_io"`
|
||||
Disk []disk.PartitionStat `json:"disk"`
|
||||
DiskUsage map[string]*disk.UsageStat `json:"disk_usage"`
|
||||
Process []*process.Process `json:"process"`
|
||||
}
|
||||
|
||||
// GetMonitoringInfo 获取监控数据
|
||||
@@ -133,7 +39,6 @@ func GetMonitoringInfo() MonitoringInfo {
|
||||
res.Net, _ = net.IOCounters(true)
|
||||
res.DiskIO, _ = disk.IOCounters()
|
||||
res.Disk, _ = disk.Partitions(true)
|
||||
res.Process, _ = process.Processes()
|
||||
|
||||
res.DiskUsage = make(map[string]*disk.UsageStat)
|
||||
for _, partition := range res.Disk {
|
||||
@@ -146,15 +51,3 @@ func GetMonitoringInfo() MonitoringInfo {
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// IsDebian 判断是否是 Debian 系统
|
||||
func IsDebian() bool {
|
||||
_, err := os.Stat("/etc/debian_version")
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// IsRHEL 判断是否是 RHEL 系统
|
||||
func IsRHEL() bool {
|
||||
_, err := os.Stat("/etc/redhat-release")
|
||||
return err == nil
|
||||
}
|
||||
|
||||
@@ -14,51 +14,6 @@ func TestHelperTestSuite(t *testing.T) {
|
||||
suite.Run(t, &HelperTestSuite{})
|
||||
}
|
||||
|
||||
func (s *HelperTestSuite) TestEmpty() {
|
||||
s.True(Empty(""))
|
||||
s.True(Empty(nil))
|
||||
s.True(Empty([]string{}))
|
||||
s.True(Empty(map[string]string{}))
|
||||
s.True(Empty(0))
|
||||
s.True(Empty(0.0))
|
||||
s.True(Empty(false))
|
||||
|
||||
s.False(Empty(" "))
|
||||
s.False(Empty([]string{"Panel"}))
|
||||
s.False(Empty(map[string]string{"Panel": "HaoZi"}))
|
||||
s.False(Empty(1))
|
||||
s.False(Empty(1.0))
|
||||
s.False(Empty(true))
|
||||
}
|
||||
|
||||
func (s *HelperTestSuite) TestFirstElement() {
|
||||
s.Equal("HaoZi", FirstElement([]string{"HaoZi"}))
|
||||
}
|
||||
|
||||
func (s *HelperTestSuite) TestRandomNumber() {
|
||||
s.Len(RandomNumber(10), 10)
|
||||
}
|
||||
|
||||
func (s *HelperTestSuite) TestRandomString() {
|
||||
s.Len(RandomString(10), 10)
|
||||
}
|
||||
|
||||
func (s *HelperTestSuite) TestMD5() {
|
||||
s.Equal("e10adc3949ba59abbe56e057f20f883e", MD5("123456"))
|
||||
}
|
||||
|
||||
func (s *HelperTestSuite) TestFormatBytes() {
|
||||
s.Equal("1.00 B", FormatBytes(1))
|
||||
s.Equal("1.00 KB", FormatBytes(1024))
|
||||
s.Equal("1.00 MB", FormatBytes(1024*1024))
|
||||
s.Equal("1.00 GB", FormatBytes(1024*1024*1024))
|
||||
s.Equal("1.00 TB", FormatBytes(1024*1024*1024*1024))
|
||||
s.Equal("1.00 PB", FormatBytes(1024*1024*1024*1024*1024))
|
||||
s.Equal("1.00 EB", FormatBytes(1024*1024*1024*1024*1024*1024))
|
||||
s.Equal("1.00 ZB", FormatBytes(1024*1024*1024*1024*1024*1024*1024))
|
||||
s.Equal("1.00 YB", FormatBytes(1024*1024*1024*1024*1024*1024*1024*1024))
|
||||
}
|
||||
|
||||
func (s *HelperTestSuite) TestCut() {
|
||||
s.Equal("aoZ", Cut("H", "i", "HaoZi"))
|
||||
func (s *HelperTestSuite) TestGetMonitoringInfo() {
|
||||
s.NotNil(GetMonitoringInfo())
|
||||
}
|
||||
|
||||
23
packages/helpers/os.go
Normal file
23
packages/helpers/os.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
// IsDebian 判断是否是 Debian 系统
|
||||
func IsDebian() bool {
|
||||
_, err := os.Stat("/etc/debian_version")
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// IsRHEL 判断是否是 RHEL 系统
|
||||
func IsRHEL() bool {
|
||||
_, err := os.Stat("/etc/redhat-release")
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// IsArm 判断是否是 ARM 架构
|
||||
func IsArm() bool {
|
||||
return runtime.GOARCH == "arm"
|
||||
}
|
||||
27
packages/helpers/os_test.go
Normal file
27
packages/helpers/os_test.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type OSHelperTestSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func TestOSHelperTestSuite(t *testing.T) {
|
||||
suite.Run(t, &OSHelperTestSuite{})
|
||||
}
|
||||
|
||||
func (s *OSHelperTestSuite) TestIsDebian() {
|
||||
s.False(IsDebian())
|
||||
}
|
||||
|
||||
func (s *OSHelperTestSuite) TestIsRHEL() {
|
||||
s.False(IsRHEL())
|
||||
}
|
||||
|
||||
func (s *OSHelperTestSuite) TestIsArm() {
|
||||
s.False(IsArm())
|
||||
}
|
||||
96
packages/helpers/string.go
Normal file
96
packages/helpers/string.go
Normal file
@@ -0,0 +1,96 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// Empty 类似于 PHP 的 empty() 函数
|
||||
func Empty(val interface{}) bool {
|
||||
if val == nil {
|
||||
return true
|
||||
}
|
||||
v := reflect.ValueOf(val)
|
||||
switch v.Kind() {
|
||||
case reflect.String, reflect.Array:
|
||||
return v.Len() == 0
|
||||
case reflect.Map, reflect.Slice:
|
||||
return v.Len() == 0 || v.IsNil()
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
return v.IsNil()
|
||||
}
|
||||
return reflect.DeepEqual(val, reflect.Zero(v.Type()).Interface())
|
||||
}
|
||||
|
||||
// FirstElement 安全地获取 args[0],避免 panic: runtime error: index out of range
|
||||
func FirstElement(args []string) string {
|
||||
if len(args) > 0 {
|
||||
return args[0]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// RandomNumber 生成长度为 length 随机数字字符串
|
||||
func RandomNumber(length int) string {
|
||||
table := [...]byte{'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}
|
||||
b := make([]byte, length)
|
||||
n, err := io.ReadAtLeast(rand.Reader, b, length)
|
||||
if n != length {
|
||||
panic(err)
|
||||
}
|
||||
for i := 0; i < len(b); i++ {
|
||||
b[i] = table[int(b[i])%len(table)]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// RandomString 生成长度为 length 的随机字符串
|
||||
func RandomString(length int) string {
|
||||
b := make([]byte, length)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
letters := "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
for i, v := range b {
|
||||
b[i] = letters[v%byte(len(letters))]
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// MD5 生成字符串的 MD5 值
|
||||
func MD5(str string) string {
|
||||
return fmt.Sprintf("%x", md5.Sum([]byte(str)))
|
||||
}
|
||||
|
||||
// FormatBytes 格式化bytes
|
||||
func FormatBytes(size float64) string {
|
||||
units := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
|
||||
|
||||
i := 0
|
||||
for ; size >= 1024 && i < len(units); i++ {
|
||||
size /= 1024
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%.2f %s", size, units[i])
|
||||
}
|
||||
|
||||
// Cut 裁剪字符串
|
||||
func Cut(begin, end, str string) string {
|
||||
b := utf8.RuneCountInString(str[:strings.Index(str, begin)]) + utf8.RuneCountInString(begin)
|
||||
e := utf8.RuneCountInString(str[:strings.Index(str, end)]) - b
|
||||
return string([]rune(str)[b : b+e])
|
||||
}
|
||||
64
packages/helpers/string_test.go
Normal file
64
packages/helpers/string_test.go
Normal file
@@ -0,0 +1,64 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type StringHelperTestSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func TestStringHelperTestSuite(t *testing.T) {
|
||||
suite.Run(t, &StringHelperTestSuite{})
|
||||
}
|
||||
|
||||
func (s *StringHelperTestSuite) TestEmpty() {
|
||||
s.True(Empty(""))
|
||||
s.True(Empty(nil))
|
||||
s.True(Empty([]string{}))
|
||||
s.True(Empty(map[string]string{}))
|
||||
s.True(Empty(0))
|
||||
s.True(Empty(0.0))
|
||||
s.True(Empty(false))
|
||||
|
||||
s.False(Empty(" "))
|
||||
s.False(Empty([]string{"Panel"}))
|
||||
s.False(Empty(map[string]string{"Panel": "HaoZi"}))
|
||||
s.False(Empty(1))
|
||||
s.False(Empty(1.0))
|
||||
s.False(Empty(true))
|
||||
}
|
||||
|
||||
func (s *StringHelperTestSuite) TestFirstElement() {
|
||||
s.Equal("HaoZi", FirstElement([]string{"HaoZi"}))
|
||||
}
|
||||
|
||||
func (s *StringHelperTestSuite) TestRandomNumber() {
|
||||
s.Len(RandomNumber(10), 10)
|
||||
}
|
||||
|
||||
func (s *StringHelperTestSuite) TestRandomString() {
|
||||
s.Len(RandomString(10), 10)
|
||||
}
|
||||
|
||||
func (s *StringHelperTestSuite) TestMD5() {
|
||||
s.Equal("e10adc3949ba59abbe56e057f20f883e", MD5("123456"))
|
||||
}
|
||||
|
||||
func (s *StringHelperTestSuite) TestFormatBytes() {
|
||||
s.Equal("1.00 B", FormatBytes(1))
|
||||
s.Equal("1.00 KB", FormatBytes(1024))
|
||||
s.Equal("1.00 MB", FormatBytes(1024*1024))
|
||||
s.Equal("1.00 GB", FormatBytes(1024*1024*1024))
|
||||
s.Equal("1.00 TB", FormatBytes(1024*1024*1024*1024))
|
||||
s.Equal("1.00 PB", FormatBytes(1024*1024*1024*1024*1024))
|
||||
s.Equal("1.00 EB", FormatBytes(1024*1024*1024*1024*1024*1024))
|
||||
s.Equal("1.00 ZB", FormatBytes(1024*1024*1024*1024*1024*1024*1024))
|
||||
s.Equal("1.00 YB", FormatBytes(1024*1024*1024*1024*1024*1024*1024*1024))
|
||||
}
|
||||
|
||||
func (s *StringHelperTestSuite) TestCut() {
|
||||
s.Equal("aoZ", Cut("H", "i", "HaoZi"))
|
||||
}
|
||||
45
packages/str/str_test.go
Normal file
45
packages/str/str_test.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package str
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type StrTestSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func TestStrTestSuite(t *testing.T) {
|
||||
suite.Run(t, &StrTestSuite{})
|
||||
}
|
||||
|
||||
func (s *StrTestSuite) TestPlural() {
|
||||
s.Equal("users", Plural("user"))
|
||||
s.Equal("users", Plural("users"))
|
||||
}
|
||||
|
||||
func (s *StrTestSuite) TestSingular() {
|
||||
s.Equal("user", Singular("users"))
|
||||
s.Equal("user", Singular("user"))
|
||||
}
|
||||
|
||||
func (s *StrTestSuite) TestSnake() {
|
||||
s.Equal("topic_comment", Snake("TopicComment"))
|
||||
s.Equal("topic_comment", Snake("topic_comment"))
|
||||
}
|
||||
|
||||
func (s *StrTestSuite) TestCamel() {
|
||||
s.Equal("TopicComment", Camel("topic_comment"))
|
||||
s.Equal("TopicComment", Camel("TopicComment"))
|
||||
}
|
||||
|
||||
func (s *StrTestSuite) TestLowerCamel() {
|
||||
s.Equal("topicComment", LowerCamel("topic_comment"))
|
||||
s.Equal("topicComment", LowerCamel("TopicComment"))
|
||||
}
|
||||
|
||||
func (s *StrTestSuite) TestContainsString() {
|
||||
s.True(ContainsString([]string{"a", "b", "c"}, "a"))
|
||||
s.False(ContainsString([]string{"a", "b", "c"}, "d"))
|
||||
}
|
||||
Reference in New Issue
Block a user