diff --git a/packages/captcha/captcha_test.go b/packages/captcha/captcha_test.go new file mode 100644 index 00000000..f88b0c5d --- /dev/null +++ b/packages/captcha/captcha_test.go @@ -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) +} diff --git a/packages/helpers/helpers.go b/packages/helpers/helpers.go index 225d1b29..36749eb8 100644 --- a/packages/helpers/helpers.go +++ b/packages/helpers/helpers.go @@ -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 -} diff --git a/packages/helpers/helpers_test.go b/packages/helpers/helpers_test.go index d839d25c..ba78a7fa 100644 --- a/packages/helpers/helpers_test.go +++ b/packages/helpers/helpers_test.go @@ -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()) } diff --git a/packages/helpers/os.go b/packages/helpers/os.go new file mode 100644 index 00000000..9f7c2610 --- /dev/null +++ b/packages/helpers/os.go @@ -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" +} diff --git a/packages/helpers/os_test.go b/packages/helpers/os_test.go new file mode 100644 index 00000000..bcd63a42 --- /dev/null +++ b/packages/helpers/os_test.go @@ -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()) +} diff --git a/packages/helpers/string.go b/packages/helpers/string.go new file mode 100644 index 00000000..c80bbc12 --- /dev/null +++ b/packages/helpers/string.go @@ -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]) +} diff --git a/packages/helpers/string_test.go b/packages/helpers/string_test.go new file mode 100644 index 00000000..40a61205 --- /dev/null +++ b/packages/helpers/string_test.go @@ -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")) +} diff --git a/packages/str/str_test.go b/packages/str/str_test.go new file mode 100644 index 00000000..de962ac5 --- /dev/null +++ b/packages/str/str_test.go @@ -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")) +}