469 lines
10 KiB
Go
469 lines
10 KiB
Go
// uSockets 功能验证测试
|
|
// go run benchmark/usockets_verify.go
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
const baseURL = "http://127.0.0.1:9998"
|
|
|
|
func main() {
|
|
fmt.Println("╔═══════════════════════════════════════════════════════════════╗")
|
|
fmt.Println("║ uSockets 集成测试 ║")
|
|
fmt.Println("╚═══════════════════════════════════════════════════════════════╝")
|
|
fmt.Println()
|
|
|
|
client := &http.Client{Timeout: 5 * time.Second}
|
|
|
|
// 检查服务器
|
|
fmt.Print("🔍 检查测试服务器... ")
|
|
if !checkServer(client) {
|
|
fmt.Println("❌ 服务器未运行")
|
|
return
|
|
}
|
|
fmt.Println("✅")
|
|
fmt.Println()
|
|
|
|
total, passed, failed := 0, 0, 0
|
|
var errors []string
|
|
|
|
// 1. 基本 GET 路由测试
|
|
fmt.Println("📦 1. 基本 GET 路由测试")
|
|
|
|
total++
|
|
fmt.Print(" 🧪 GET 根路径... ")
|
|
if checkGetRoot(client) {
|
|
passed++
|
|
fmt.Println("✅")
|
|
} else {
|
|
failed++
|
|
errors = append(errors, "GET 根路径")
|
|
fmt.Println("❌")
|
|
}
|
|
|
|
total++
|
|
fmt.Print(" 🧪 GET 健康检查... ")
|
|
if checkGetHealth(client) {
|
|
passed++
|
|
fmt.Println("✅")
|
|
} else {
|
|
failed++
|
|
errors = append(errors, "GET 健康检查")
|
|
fmt.Println("❌")
|
|
}
|
|
|
|
total++
|
|
fmt.Print(" 🧪 GET 静态路由... ")
|
|
if checkGetStatic(client) {
|
|
passed++
|
|
fmt.Println("✅")
|
|
} else {
|
|
failed++
|
|
errors = append(errors, "GET 静态路由")
|
|
fmt.Println("❌")
|
|
}
|
|
fmt.Println()
|
|
|
|
// 2. 动态路由测试
|
|
fmt.Println("📦 2. 动态路由测试")
|
|
|
|
total++
|
|
fmt.Print(" 🧪 单参数路由... ")
|
|
if checkSingleParam(client) {
|
|
passed++
|
|
fmt.Println("✅")
|
|
} else {
|
|
failed++
|
|
errors = append(errors, "单参数路由")
|
|
fmt.Println("❌")
|
|
}
|
|
|
|
total++
|
|
fmt.Print(" 🧪 多参数路由... ")
|
|
if checkMultiParams(client) {
|
|
passed++
|
|
fmt.Println("✅")
|
|
} else {
|
|
failed++
|
|
errors = append(errors, "多参数路由")
|
|
fmt.Println("❌")
|
|
}
|
|
|
|
total++
|
|
fmt.Print(" 🧪 嵌套参数路由... ")
|
|
if checkNestedParams(client) {
|
|
passed++
|
|
fmt.Println("✅")
|
|
} else {
|
|
failed++
|
|
errors = append(errors, "嵌套参数路由")
|
|
fmt.Println("❌")
|
|
}
|
|
fmt.Println()
|
|
|
|
// 3. 查询参数测试
|
|
fmt.Println("📦 3. 查询参数测试")
|
|
|
|
total++
|
|
fmt.Print(" 🧪 单个查询参数... ")
|
|
if checkSingleQuery(client) {
|
|
passed++
|
|
fmt.Println("✅")
|
|
} else {
|
|
failed++
|
|
errors = append(errors, "单个查询参数")
|
|
fmt.Println("❌")
|
|
}
|
|
|
|
total++
|
|
fmt.Print(" 🧪 多个查询参数... ")
|
|
if checkMultiQuery(client) {
|
|
passed++
|
|
fmt.Println("✅")
|
|
} else {
|
|
failed++
|
|
errors = append(errors, "多个查询参数")
|
|
fmt.Println("❌")
|
|
}
|
|
fmt.Println()
|
|
|
|
// 4. 响应格式测试
|
|
fmt.Println("📦 4. 响应格式测试")
|
|
|
|
total++
|
|
fmt.Print(" 🧪 JSON 响应... ")
|
|
if checkJSONResponse(client) {
|
|
passed++
|
|
fmt.Println("✅")
|
|
} else {
|
|
failed++
|
|
errors = append(errors, "JSON 响应")
|
|
fmt.Println("❌")
|
|
}
|
|
|
|
total++
|
|
fmt.Print(" 🧪 HTML 响应... ")
|
|
if checkHTMLResponse(client) {
|
|
passed++
|
|
fmt.Println("✅")
|
|
} else {
|
|
failed++
|
|
errors = append(errors, "HTML 响应")
|
|
fmt.Println("❌")
|
|
}
|
|
|
|
total++
|
|
fmt.Print(" 🧪 自定义状态码 201... ")
|
|
if checkCustomStatus(client) {
|
|
passed++
|
|
fmt.Println("✅")
|
|
} else {
|
|
failed++
|
|
errors = append(errors, "自定义状态码 201")
|
|
fmt.Println("❌")
|
|
}
|
|
fmt.Println()
|
|
|
|
// 5. HTTP 方法测试
|
|
fmt.Println("📦 5. HTTP 方法测试")
|
|
|
|
total++
|
|
fmt.Print(" 🧪 POST 请求... ")
|
|
if checkPOST(client) {
|
|
passed++
|
|
fmt.Println("✅")
|
|
} else {
|
|
failed++
|
|
errors = append(errors, "POST 请求")
|
|
fmt.Println("❌")
|
|
}
|
|
|
|
total++
|
|
fmt.Print(" 🧪 PUT 请求... ")
|
|
if checkPUT(client) {
|
|
passed++
|
|
fmt.Println("✅")
|
|
} else {
|
|
failed++
|
|
errors = append(errors, "PUT 请求")
|
|
fmt.Println("❌")
|
|
}
|
|
|
|
total++
|
|
fmt.Print(" 🧪 DELETE 请求... ")
|
|
if checkDELETE(client) {
|
|
passed++
|
|
fmt.Println("✅")
|
|
} else {
|
|
failed++
|
|
errors = append(errors, "DELETE 请求")
|
|
fmt.Println("❌")
|
|
}
|
|
fmt.Println()
|
|
|
|
// 6. 错误处理测试
|
|
fmt.Println("📦 6. 错误处理测试")
|
|
|
|
total++
|
|
fmt.Print(" 🧪 404 未找到... ")
|
|
if checkNotFound(client) {
|
|
passed++
|
|
fmt.Println("✅")
|
|
} else {
|
|
failed++
|
|
errors = append(errors, "404 未找到")
|
|
fmt.Println("❌")
|
|
}
|
|
fmt.Println()
|
|
|
|
// 7. Keep-Alive 测试
|
|
fmt.Println("📦 7. Keep-Alive 连接测试")
|
|
|
|
total++
|
|
fmt.Print(" 🧪 连接复用... ")
|
|
if checkKeepAlive(client) {
|
|
passed++
|
|
fmt.Println("✅")
|
|
} else {
|
|
failed++
|
|
errors = append(errors, "连接复用")
|
|
fmt.Println("❌")
|
|
}
|
|
fmt.Println()
|
|
|
|
// 8. 性能测试
|
|
fmt.Println("📦 8. 性能测试")
|
|
|
|
total++
|
|
fmt.Print(" 🧪 吞吐量测试... ")
|
|
rps := checkThroughput(client)
|
|
if rps > 100 {
|
|
passed++
|
|
fmt.Printf("✅ (%.0f req/s)\n", rps)
|
|
} else {
|
|
failed++
|
|
errors = append(errors, "吞吐量")
|
|
fmt.Printf("❌ (%.0f req/s)\n", rps)
|
|
}
|
|
fmt.Println()
|
|
|
|
// 输出总结
|
|
fmt.Println("═══════════════════════════════════════════════════════════════")
|
|
fmt.Printf("📊 测试结果: %d/%d 通过\n", passed, total)
|
|
|
|
if failed > 0 {
|
|
fmt.Println("❌ 失败的测试:")
|
|
for _, err := range errors {
|
|
fmt.Printf(" - %s\n", err)
|
|
}
|
|
} else {
|
|
fmt.Println("🎉 所有测试通过!uSockets 后端验证成功!")
|
|
}
|
|
fmt.Println("═══════════════════════════════════════════════════════════════")
|
|
}
|
|
|
|
func checkServer(client *http.Client) bool {
|
|
resp, err := client.Get(baseURL + "/health")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer resp.Body.Close()
|
|
return resp.StatusCode == 200
|
|
}
|
|
|
|
func getBody(resp *http.Response) string {
|
|
body, _ := io.ReadAll(resp.Body)
|
|
return string(body)
|
|
}
|
|
|
|
func checkGetRoot(client *http.Client) bool {
|
|
resp, err := client.Get(baseURL + "/")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer resp.Body.Close()
|
|
body := getBody(resp)
|
|
return resp.StatusCode == 200 && strings.Contains(body, "Hello")
|
|
}
|
|
|
|
func checkGetHealth(client *http.Client) bool {
|
|
resp, err := client.Get(baseURL + "/health")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer resp.Body.Close()
|
|
body := getBody(resp)
|
|
return resp.StatusCode == 200 && body == "OK"
|
|
}
|
|
|
|
func checkGetStatic(client *http.Client) bool {
|
|
resp, err := client.Get(baseURL + "/api/health")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer resp.Body.Close()
|
|
body := getBody(resp)
|
|
return resp.StatusCode == 200 && body == "OK"
|
|
}
|
|
|
|
func checkSingleParam(client *http.Client) bool {
|
|
resp, err := client.Get(baseURL + "/api/users/456")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer resp.Body.Close()
|
|
body := getBody(resp)
|
|
return resp.StatusCode == 200 && strings.Contains(body, "456")
|
|
}
|
|
|
|
func checkMultiParams(client *http.Client) bool {
|
|
resp, err := client.Get(baseURL + "/api/users/123/posts/789")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer resp.Body.Close()
|
|
body := getBody(resp)
|
|
return resp.StatusCode == 200 && strings.Contains(body, "123") && strings.Contains(body, "789")
|
|
}
|
|
|
|
func checkNestedParams(client *http.Client) bool {
|
|
resp, err := client.Get(baseURL + "/api/categories/tech/items/laptop")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer resp.Body.Close()
|
|
body := getBody(resp)
|
|
return resp.StatusCode == 200 && strings.Contains(body, "tech") && strings.Contains(body, "laptop")
|
|
}
|
|
|
|
func checkSingleQuery(client *http.Client) bool {
|
|
resp, err := client.Get(baseURL + "/api/search?q=test")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer resp.Body.Close()
|
|
body := getBody(resp)
|
|
return resp.StatusCode == 200 && strings.Contains(body, "test")
|
|
}
|
|
|
|
func checkMultiQuery(client *http.Client) bool {
|
|
resp, err := client.Get(baseURL + "/api/search?q=hello&limit=10&page=1")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer resp.Body.Close()
|
|
body := getBody(resp)
|
|
return resp.StatusCode == 200 && strings.Contains(body, "hello")
|
|
}
|
|
|
|
func checkJSONResponse(client *http.Client) bool {
|
|
resp, err := client.Get(baseURL + "/api/json")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer resp.Body.Close()
|
|
ct := resp.Header.Get("Content-Type")
|
|
return resp.StatusCode == 200 && strings.Contains(ct, "application/json")
|
|
}
|
|
|
|
func checkHTMLResponse(client *http.Client) bool {
|
|
resp, err := client.Get(baseURL + "/api/html")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer resp.Body.Close()
|
|
ct := resp.Header.Get("Content-Type")
|
|
return resp.StatusCode == 200 && strings.Contains(ct, "text/html")
|
|
}
|
|
|
|
func checkCustomStatus(client *http.Client) bool {
|
|
resp, err := client.Get(baseURL + "/api/created")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer resp.Body.Close()
|
|
return resp.StatusCode == 201
|
|
}
|
|
|
|
func checkPOST(client *http.Client) bool {
|
|
resp, err := client.Post(baseURL+"/api/users", "application/json", nil)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer resp.Body.Close()
|
|
body := getBody(resp)
|
|
return resp.StatusCode == 201 && strings.Contains(body, "created")
|
|
}
|
|
|
|
func checkPUT(client *http.Client) bool {
|
|
req, _ := http.NewRequest("PUT", baseURL+"/api/users/123", nil)
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer resp.Body.Close()
|
|
body := getBody(resp)
|
|
return resp.StatusCode == 200 && strings.Contains(body, "updated")
|
|
}
|
|
|
|
func checkDELETE(client *http.Client) bool {
|
|
req, _ := http.NewRequest("DELETE", baseURL+"/api/users/123", nil)
|
|
resp, err := client.Do(req)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer resp.Body.Close()
|
|
body := getBody(resp)
|
|
return resp.StatusCode == 200 && strings.Contains(body, "deleted")
|
|
}
|
|
|
|
func checkNotFound(client *http.Client) bool {
|
|
resp, err := client.Get(baseURL + "/nonexistent/path")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer resp.Body.Close()
|
|
return resp.StatusCode == 404
|
|
}
|
|
|
|
func checkKeepAlive(client *http.Client) bool {
|
|
for i := 0; i < 10; i++ {
|
|
resp, err := client.Get(baseURL + "/health")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
resp.Body.Close()
|
|
if resp.StatusCode != 200 {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
func checkThroughput(client *http.Client) float64 {
|
|
start := time.Now()
|
|
success := 0
|
|
requests := 200
|
|
|
|
for i := 0; i < requests; i++ {
|
|
resp, err := client.Get(baseURL + "/health")
|
|
if err != nil {
|
|
continue
|
|
}
|
|
io.Copy(io.Discard, resp.Body)
|
|
resp.Body.Close()
|
|
if resp.StatusCode == 200 {
|
|
success++
|
|
}
|
|
}
|
|
|
|
elapsed := time.Since(start).Seconds()
|
|
return float64(success) / elapsed
|
|
}
|