From 8289e2b4d9503a0b66f8a4b3a25118bfd2ccc79f Mon Sep 17 00:00:00 2001 From: "DESKTOP-V763RJ7\\Administrator" <835606593@qq.com> Date: Mon, 5 Jan 2026 00:32:23 +0800 Subject: [PATCH] =?UTF-8?q?feat=20=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/config.go | 14 +- deploy/Jenkinsfile | 50 +++--- go.mod | 10 +- go.sum | 19 ++- internal/handler/http_handler/login.go | 2 +- internal/handler/http_handler/login_test.go | 171 ++++++++++++++++++++ internal/handler/http_handler/test.go | 27 ---- internal/net/http_gateway/router.go | 1 - internal/testutil/suite.go | 52 ++++++ 9 files changed, 283 insertions(+), 63 deletions(-) create mode 100644 internal/handler/http_handler/login_test.go delete mode 100644 internal/handler/http_handler/test.go create mode 100644 internal/testutil/suite.go diff --git a/config/config.go b/config/config.go index 9d14ea8..2e4b389 100644 --- a/config/config.go +++ b/config/config.go @@ -19,10 +19,12 @@ type Config struct { Metric *config.MetricConfig `yaml:"metric"` DB *config.DBConfig `yaml:"db"` Serve *config.ServeConfig `yaml:"serve"` - Auth *struct { - Secret string `yaml:"secret"` - Expire int64 `yaml:"expire"` - } + Auth *AuthConfig `yaml:"auth"` +} + +type AuthConfig struct { + Secret string `yaml:"secret"` + Expire int64 `yaml:"expire"` } var cfg *Config @@ -37,3 +39,7 @@ func LoadConfig() error { func Get() *Config { return cfg } + +func Set(c *Config) { + cfg = c +} diff --git a/deploy/Jenkinsfile b/deploy/Jenkinsfile index c3a6655..a5fd71c 100644 --- a/deploy/Jenkinsfile +++ b/deploy/Jenkinsfile @@ -3,7 +3,7 @@ pipeline { environment { // 仓库 - REPO_URL = 'http://47.108.184.184/gitea/HuXiaoHei/Game.git' + REPO_URL = 'http://47.108.184.184/gitea/mmorpg/service-gateway.git' REPO_CREDENTIALS_ID = '80805ba2-f4ac-4d84-aee6-d4cce5fc0a96' // Registry @@ -16,7 +16,7 @@ pipeline { SSH_CREDENTIALS_ID = '10e0830d-4d03-4879-9ee4-03a4c55513ad' // 基础信息 - APP_NAME = 'server-gateway' + APP_NAME = 'service-gateway' GO_MOD_CACHE_DIR = '/home/pi/Desktop/docker/jenkins/caches/go-mod' GO_BUILD_CACHE_DIR = '/home/pi/Desktop/docker/jenkins/caches/go-build' } @@ -57,37 +57,33 @@ pipeline { } } steps { - dir('Server/gateway') { - sh """ - export GOPROXY=https://goproxy.cn,direct - export CGO_ENABLED=0 - export GOOS=linux - export GOARCH=amd64 + sh """ + export GOPROXY=https://goproxy.cn,direct + export CGO_ENABLED=0 + export GOOS=linux + export GOARCH=amd64 - go build -o ${env.APP_NAME} . - """ - } + go build -o ${env.APP_NAME} . + """ } } stage('Push Docker Image') { agent any steps { - dir('Server/gateway') { - script { - withCredentials([usernamePassword( - credentialsId: env.REGISTRY_CREDENTIALS_ID, - usernameVariable: 'DOCKER_USER', - passwordVariable: 'DOCKER_PASS' - )]) { - sh """ - echo "$DOCKER_PASS" | docker login --username "$DOCKER_USER" --password-stdin ${env.REGISTRY_URL} - docker build -t ${env.IMAGE_TAG} . - docker push ${env.IMAGE_TAG} - docker rmi ${env.IMAGE_TAG} - docker logout ${env.REGISTRY_URL} - """ - } + script { + withCredentials([usernamePassword( + credentialsId: env.REGISTRY_CREDENTIALS_ID, + usernameVariable: 'DOCKER_USER', + passwordVariable: 'DOCKER_PASS' + )]) { + sh """ + echo "$DOCKER_PASS" | docker login --username "$DOCKER_USER" --password-stdin ${env.REGISTRY_URL} + docker build -t ${env.IMAGE_TAG} . + docker push ${env.IMAGE_TAG} + docker rmi ${env.IMAGE_TAG} + docker logout ${env.REGISTRY_URL} + """ } } } @@ -117,7 +113,7 @@ pipeline { --restart unless-stopped \\ -p 8500-8504:8500-8504 \\ --env XH_G_ENV=prod \\ - -v /root/server/logs/gateway_log/:/app/logs \\ + -v /root/service/logs/gateway_log/:/app/logs \\ ${env.IMAGE_TAG} docker logout ${env.REGISTRY_URL} """ diff --git a/go.mod b/go.mod index 9c6aaa9..c15e3d3 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,17 @@ module gateway go 1.23.1 require ( + bou.ke/monkey v1.0.2 common v0.0.0-00010101000000-000000000000 + github.com/alicebob/miniredis/v2 v2.35.0 github.com/gin-contrib/cors v1.7.6 github.com/gin-gonic/gin v1.11.0 + github.com/golang/mock v1.6.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 github.com/judwhite/go-svc v1.2.1 + github.com/panjf2000/gnet/v2 v2.9.7 github.com/prometheus/client_golang v1.20.5 + github.com/stretchr/testify v1.11.1 go.uber.org/zap v1.27.0 google.golang.org/grpc v1.71.1 google.golang.org/protobuf v1.36.9 @@ -24,6 +29,7 @@ require ( github.com/cloudwego/base64x v0.1.6 // indirect github.com/coreos/go-semver v0.3.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/gabriel-vasile/mimetype v1.4.9 // indirect @@ -53,8 +59,8 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/natefinch/lumberjack v2.0.0+incompatible // indirect github.com/panjf2000/ants/v2 v2.11.3 // indirect - github.com/panjf2000/gnet/v2 v2.9.7 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.15.1 // indirect @@ -71,6 +77,7 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.3.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/yuin/gopher-lua v1.1.1 // indirect go.etcd.io/etcd/api/v3 v3.6.1 // indirect go.etcd.io/etcd/client/pkg/v3 v3.6.1 // indirect go.etcd.io/etcd/client/v3 v3.6.1 // indirect @@ -88,6 +95,7 @@ require ( google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect gorm.io/driver/mysql v1.6.0 // indirect gorm.io/gorm v1.31.1 // indirect ) diff --git a/go.sum b/go.sum index e914118..f0883d3 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,11 @@ +bou.ke/monkey v1.0.2 h1:kWcnsrCNUatbxncxR/ThdYqbytgOIArtYWqcQLQzKLI= +bou.ke/monkey v1.0.2/go.mod h1:OqickVX3tNx6t33n1xvtTtu85YN5s6cKwVug+oHMaIA= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/alicebob/miniredis/v2 v2.35.0 h1:QwLphYqCEAo1eu1TqPRN2jgVMPBweeQcR21jeqDCONI= +github.com/alicebob/miniredis/v2 v2.35.0/go.mod h1:TcL7YfarKPGDAthEtl5NBeHZfeUQj6OXMm/+iu5cLMM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= @@ -70,6 +74,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= @@ -114,8 +120,6 @@ github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4 github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk= github.com/panjf2000/ants/v2 v2.11.3 h1:AfI0ngBoXJmYOpDh9m516vjqoUu2sLrIVgppI9TZVpg= github.com/panjf2000/ants/v2 v2.11.3/go.mod h1:8u92CYMUc6gyvTIw8Ru7Mt7+/ESnJahz5EVtqfrilek= -github.com/panjf2000/gnet/v2 v2.9.1 h1:bKewICy/0xnQ9PMzNaswpe/Ah14w1TrRk91LHTcbIlA= -github.com/panjf2000/gnet/v2 v2.9.1/go.mod h1:WQTxDWYuQ/hz3eccH0FN32IVuvZ19HewEWx0l62fx7E= github.com/panjf2000/gnet/v2 v2.9.7 h1:6zW7Jl3oAfXwSuh1PxHLndoL2MQRWx0AJR6aaQjxUgA= github.com/panjf2000/gnet/v2 v2.9.7/go.mod h1:WQTxDWYuQ/hz3eccH0FN32IVuvZ19HewEWx0l62fx7E= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= @@ -169,6 +173,9 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M= +github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= go.etcd.io/etcd/api/v3 v3.6.1 h1:yJ9WlDih9HT457QPuHt/TH/XtsdN2tubyxyQHSHPsEo= go.etcd.io/etcd/api/v3 v3.6.1/go.mod h1:lnfuqoGsXMlZdTJlact3IB56o3bWp1DIlXPIGKRArto= go.etcd.io/etcd/client/pkg/v3 v3.6.1 h1:CxDVv8ggphmamrXM4Of8aCC8QHzDM4tGcVr9p2BSoGk= @@ -206,26 +213,33 @@ golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= @@ -234,6 +248,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/internal/handler/http_handler/login.go b/internal/handler/http_handler/login.go index 897ce5f..28f1f4d 100644 --- a/internal/handler/http_handler/login.go +++ b/internal/handler/http_handler/login.go @@ -79,7 +79,7 @@ func RefreshToken(c *gin.Context) { http_resp.JsonOK(c, http_resp.Error(http_resp.TokenInvalid)) return } - if redis.GetClient().Get(c, fmt.Sprintf(config.KeyUserRefreshToken, claims.USN)).String() != req.RefreshToken { + if redis.GetClient().Get(c, fmt.Sprintf(config.KeyUserRefreshToken, claims.USN)).Val() != req.RefreshToken { http_resp.JsonOK(c, http_resp.Error(http_resp.TokenInvalid)) return } diff --git a/internal/handler/http_handler/login_test.go b/internal/handler/http_handler/login_test.go new file mode 100644 index 0000000..20aff21 --- /dev/null +++ b/internal/handler/http_handler/login_test.go @@ -0,0 +1,171 @@ +package http_handler + +import ( + "bou.ke/monkey" + "common/db/redis" + "common/net/grpc/service" + "common/net/http/http_resp" + "common/proto/ss/grpc_pb" + "common/proto/ss/grpc_pb/mocks" + "common/utils" + "context" + "fmt" + "gateway/config" + "gateway/internal/testutil" + "github.com/gin-gonic/gin" + "github.com/golang/mock/gomock" + redis2 "github.com/redis/go-redis/v9" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/suite" + "net/http" + "testing" +) + +type LoginTestSuite struct { + testutil.TestSuite +} + +func (ts *LoginTestSuite) TestGenToken() { + usn := utils.RandInt(1, 100000000) + at, rt, err := genToken(context.Background(), int64(usn)) + ts.Assert().NoError(err) + + redisAt := redis.GetClient().Get(context.Background(), fmt.Sprintf(config.KeyUserAccessToken, usn)).Val() + ts.Assert().Equal(at, redisAt) + redisRt := redis.GetClient().Get(context.Background(), fmt.Sprintf(config.KeyUserRefreshToken, usn)).Val() + ts.Assert().Equal(rt, redisRt) +} + +func (ts *LoginTestSuite) TestLogin() { + gin.SetMode(gin.TestMode) + + ts.Run("ShouldBindJSON Failed", func() { + w, c := utils.CreateTestContext("POST", "/", &LoginReq{ + Phone: "", + Code: "", + }) + Login(c) + utils.AssertResponse(&ts.Suite, w, http.StatusBadRequest, http_resp.ParamError) + }) + + ts.Run("UserNewClientLB Failed", func() { + monkey.Patch(service.UserNewClientLB, func() (grpc_pb.UserClient, error) { + return nil, assert.AnError + }) + defer monkey.Unpatch(service.UserNewClientLB) + + w, c := utils.CreateTestContext("POST", "/", &LoginReq{ + Phone: "13800000000", + Code: "1234", + }) + Login(c) + utils.AssertResponse(&ts.Suite, w, http.StatusOK, http_resp.Failed) + }) + + ts.Run("Login Failed", func() { + ctrl := gomock.NewController(ts.T()) + defer ctrl.Finish() + client := mocks.NewMockUserClient(ctrl) + client.EXPECT(). + Login(gomock.Any(), gomock.Any()). + Return(nil, fmt.Errorf("gRPC failed")) + + monkey.Patch(service.UserNewClientLB, func() (grpc_pb.UserClient, error) { + return client, nil + }) + defer monkey.Unpatch(service.UserNewClientLB) + + w, c := utils.CreateTestContext("POST", "/", &LoginReq{ + Phone: "13800000000", + Code: "1234", + }) + Login(c) + utils.AssertResponse(&ts.Suite, w, http.StatusOK, http_resp.Failed) + }) + + ts.Run("OK", func() { + ctrl := gomock.NewController(ts.T()) + defer ctrl.Finish() + client := mocks.NewMockUserClient(ctrl) + client.EXPECT(). + Login(gomock.Any(), gomock.Any()). + Return(&grpc_pb.LoginResp{USN: 1, Name: "hh"}, nil) + + monkey.Patch(service.UserNewClientLB, func() (grpc_pb.UserClient, error) { + return client, nil + }) + defer monkey.Unpatch(service.UserNewClientLB) + + w, c := utils.CreateTestContext("POST", "/", &LoginReq{ + Phone: "13800000000", + Code: "1234", + }) + Login(c) + utils.AssertResponse(&ts.Suite, w, http.StatusOK, http_resp.OK) + }) +} + +func (ts *LoginTestSuite) TestRefreshToken() { + gin.SetMode(gin.TestMode) + + ts.Run("ShouldBindJSON Failed", func() { + w, c := utils.CreateTestContext("POST", "/", &RefreshTokenReq{ + RefreshToken: "", + }) + RefreshToken(c) + utils.AssertResponse(&ts.Suite, w, http.StatusBadRequest, http_resp.ParamError) + }) + + ts.Run("ParseToken Failed", func() { + monkey.Patch(utils.ParseToken, func(tokenString string, secret string) (*utils.Claims, error) { + return nil, assert.AnError + }) + defer monkey.Unpatch(utils.ParseToken) + + w, c := utils.CreateTestContext("POST", "/", &RefreshTokenReq{ + RefreshToken: "abc", + }) + RefreshToken(c) + utils.AssertResponse(&ts.Suite, w, http.StatusOK, http_resp.TokenInvalid) + }) + + ts.Run("Redis Get Failed", func() { + monkey.Patch(utils.ParseToken, func(tokenString string, secret string) (*utils.Claims, error) { + if tokenString == "abc" { + return &utils.Claims{USN: 1}, nil + } + return nil, assert.AnError + }) + defer monkey.Unpatch(utils.ParseToken) + + redis.GetClient().Set(context.Background(), fmt.Sprintf(config.KeyUserRefreshToken, 1), "ab", redis2.KeepTTL) + + w, c := utils.CreateTestContext("POST", "/", &RefreshTokenReq{ + RefreshToken: "abc", + }) + RefreshToken(c) + utils.AssertResponse(&ts.Suite, w, http.StatusOK, http_resp.TokenInvalid) + }) + + ts.Run("OK", func() { + monkey.Patch(utils.ParseToken, func(tokenString string, secret string) (*utils.Claims, error) { + if tokenString == "abc" { + return &utils.Claims{USN: 1}, nil + } + return nil, assert.AnError + }) + defer monkey.Unpatch(utils.ParseToken) + + redis.GetClient().Set(context.Background(), fmt.Sprintf(config.KeyUserRefreshToken, 1), "abc", redis2.KeepTTL) + + w, c := utils.CreateTestContext("POST", "/", &RefreshTokenReq{ + RefreshToken: "abc", + }) + RefreshToken(c) + utils.AssertResponse(&ts.Suite, w, http.StatusOK, http_resp.OK) + }) +} + +func TestLoginTestSuite(t *testing.T) { + suite.Run(t, &LoginTestSuite{}) +} diff --git a/internal/handler/http_handler/test.go b/internal/handler/http_handler/test.go deleted file mode 100644 index eaf5a3b..0000000 --- a/internal/handler/http_handler/test.go +++ /dev/null @@ -1,27 +0,0 @@ -package http_handler - -import ( - "common/net/http/http_resp" - "github.com/gin-gonic/gin" -) - -// 这个模块处理用户登录 - -type TestReq struct { -} - -type TestResp struct { - Info string `json:"info"` -} - -func Test(c *gin.Context) { - req := &TestReq{} - if err := c.ShouldBindJSON(req); err != nil { - http_resp.JsonBadRequest(c) - return - } - - http_resp.JsonOK(c, http_resp.Success(&TestResp{ - Info: "成功了", - })) -} diff --git a/internal/net/http_gateway/router.go b/internal/net/http_gateway/router.go index 9127bf2..c7181dd 100644 --- a/internal/net/http_gateway/router.go +++ b/internal/net/http_gateway/router.go @@ -72,7 +72,6 @@ func initBaseRoute(r *gin.RouterGroup) { g := r.Group("/gw") g.POST("/login", http_handler.Login) g.POST("/refresh_token", http_handler.RefreshToken) - g.GET("/test", http_handler.Test) } func initUserPath(r *gin.RouterGroup) { diff --git a/internal/testutil/suite.go b/internal/testutil/suite.go new file mode 100644 index 0000000..43505c6 --- /dev/null +++ b/internal/testutil/suite.go @@ -0,0 +1,52 @@ +package testutil + +import ( + config2 "common/config" + "common/db/redis" + "gateway/config" + "github.com/alicebob/miniredis/v2" + "github.com/stretchr/testify/suite" +) + +type TestSuite struct { + suite.Suite + redis *miniredis.Miniredis +} + +// SetupSuite 在整个测试套件开始前运行一次 +func (ts *TestSuite) SetupSuite() { + // Redis + r, err := miniredis.Run() + ts.Require().NoError(err) + ts.redis = r + + // Config + config.Set(&config.Config{ + DB: &config2.DBConfig{ + Redis: &config2.RedisConfig{ + Addr: r.Addr(), + }, + }, + Auth: &config.AuthConfig{ + Secret: "test", + Expire: 259200, + }, + }) + + ts.Require().NoError(redis.Init(config.Get().DB.Redis)) +} + +// TearDownSuite 在整个测试套件结束后运行一次 +func (ts *TestSuite) TearDownSuite() { + if ts.redis != nil { + ts.redis.Close() + } +} + +// SetupTest 在每个测试用例前运行 +func (ts *TestSuite) SetupTest() { +} + +// TearDownTest 在每个测试用例后运行 +func (ts *TestSuite) TearDownTest() { +}