- 替换 Beego 框架为 GoFrame v2 - 重构项目结构: controller/service/dao/middleware 分层 - 替换自定义 crons 包为 gcron - 模板从 views/ 迁移到 resource/template/ - 配置从 conf/app.conf 迁移到 config.yml - 数据库从 MySQL 切换为 SQLite (modernc.org/sqlite) - 移除 agent/ 远程执行器(待后续迁移) - 移除 crons/ 自定义定时器包 - 静态资源整理到 resource/static/
123 lines
3.3 KiB
Go
123 lines
3.3 KiB
Go
package libs
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestMd5(t *testing.T) {
|
|
tests := []struct {
|
|
input string
|
|
expected string
|
|
}{
|
|
{"hello", "5d41402abc4b2a76b9719d911017c592"},
|
|
{"123456", "e10adc3949ba59abbe56e057f20f883e"},
|
|
{"", "d41d8cd98f00b204e9800998ecf8427e"},
|
|
}
|
|
for _, tt := range tests {
|
|
result := Md5([]byte(tt.input))
|
|
if result != tt.expected {
|
|
t.Errorf("Md5(%q) = %q, want %q", tt.input, result, tt.expected)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestHashPassword(t *testing.T) {
|
|
password := "test123"
|
|
hash, salt := HashPassword(password)
|
|
|
|
if hash == "" {
|
|
t.Error("HashPassword() returned empty hash")
|
|
}
|
|
if salt == "" {
|
|
t.Error("HashPassword() returned empty salt")
|
|
}
|
|
if !strings.HasPrefix(hash, "$sha256$") {
|
|
t.Errorf("HashPassword() hash %q does not have $sha256$ prefix", hash)
|
|
}
|
|
|
|
// Verify the hash can be verified
|
|
if !VerifyPassword(password, hash, salt) {
|
|
t.Error("VerifyPassword() failed for freshly generated hash")
|
|
}
|
|
|
|
// Wrong password should fail
|
|
if VerifyPassword("wrong", hash, salt) {
|
|
t.Error("VerifyPassword() should fail for wrong password")
|
|
}
|
|
}
|
|
|
|
func TestVerifyPassword_NewFormat(t *testing.T) {
|
|
hash, salt := HashPassword("mypassword")
|
|
if !VerifyPassword("mypassword", hash, salt) {
|
|
t.Error("VerifyPassword should verify $sha256$ format")
|
|
}
|
|
if VerifyPassword("notmypassword", hash, salt) {
|
|
t.Error("VerifyPassword should reject wrong password for $sha256$ format")
|
|
}
|
|
}
|
|
|
|
func TestVerifyPassword_OldFormat(t *testing.T) {
|
|
// Old format: MD5(password + salt)
|
|
oldHash := Md5([]byte("oldpass" + "abcd"))
|
|
if !VerifyPassword("oldpass", oldHash, "abcd") {
|
|
t.Error("VerifyPassword should verify old MD5 format")
|
|
}
|
|
if VerifyPassword("wrongpass", oldHash, "abcd") {
|
|
t.Error("VerifyPassword should reject wrong password for old MD5 format")
|
|
}
|
|
}
|
|
|
|
func TestVerifyPassword_MalformedHash(t *testing.T) {
|
|
// Malformed $sha256$ hash (only 2 parts instead of 4)
|
|
malformed := "$sha256$toofew"
|
|
if VerifyPassword("anything", malformed, "salt") {
|
|
t.Error("VerifyPassword should reject malformed hash")
|
|
}
|
|
}
|
|
|
|
func TestPassword(t *testing.T) {
|
|
// Default password when empty
|
|
pwd, salt := Password(0, "")
|
|
if pwd == "" || salt == "" {
|
|
t.Error("Password() with empty input should return non-empty hash/salt")
|
|
}
|
|
if !strings.HasPrefix(pwd, "$sha256$") {
|
|
t.Errorf("Password() hash should have $sha256$ prefix, got %q", pwd)
|
|
}
|
|
|
|
// Custom password
|
|
pwd2, salt2 := Password(0, "custompass")
|
|
if pwd2 == "" || salt2 == "" {
|
|
t.Error("Password() with custom password should return non-empty hash/salt")
|
|
}
|
|
if !VerifyPassword("custompass", pwd2, salt2) {
|
|
t.Error("Password() hash should verify with original password")
|
|
}
|
|
}
|
|
|
|
func TestSha256Hex(t *testing.T) {
|
|
tests := []struct {
|
|
input string
|
|
expected string
|
|
}{
|
|
{"hello", "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"},
|
|
{"", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"},
|
|
}
|
|
for _, tt := range tests {
|
|
result := Sha256Hex([]byte(tt.input))
|
|
if result != tt.expected {
|
|
t.Errorf("Sha256Hex(%q) = %q, want %q", tt.input, result, tt.expected)
|
|
}
|
|
}
|
|
}
|
|
|
|
func FuzzVerifyPassword(f *testing.F) {
|
|
f.Add("password123", "$sha256$salt1234$ab12cd34ef56", "salt1234")
|
|
f.Add("abc", "5d41402abc4b2a76b9719d911017c592", "salt")
|
|
f.Fuzz(func(t *testing.T, password, hash, salt string) {
|
|
// Should not panic with any input
|
|
_ = VerifyPassword(password, hash, salt)
|
|
})
|
|
}
|