mirror of
https://github.com/go-kratos/kratos.git
synced 2025-01-24 03:46:37 +02:00
是我静香不够骚,还是你胖虎开始飘~
This commit is contained in:
parent
529cbc5245
commit
dd509fed54
3
go.mod
3
go.mod
@ -28,6 +28,7 @@ require (
|
||||
github.com/mattn/go-colorable v0.1.2 // indirect
|
||||
github.com/montanaflynn/stats v0.5.0
|
||||
github.com/openzipkin/zipkin-go v0.2.1
|
||||
github.com/otokaze/mock v0.0.0-20190125081256-8282b7a7c7c3
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/prometheus/client_golang v1.0.0
|
||||
github.com/prometheus/client_model v0.0.0-20190220174349-fd36f4220a90 // indirect
|
||||
@ -38,6 +39,7 @@ require (
|
||||
github.com/shirou/gopsutil v2.19.6+incompatible
|
||||
github.com/siddontang/go v0.0.0-20180604090527-bdc77568d726
|
||||
github.com/sirupsen/logrus v1.4.2
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337
|
||||
github.com/stretchr/testify v1.3.0
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 // indirect
|
||||
github.com/tsuna/gohbase v0.0.0-20190502052937-24ffed0537aa
|
||||
@ -49,6 +51,7 @@ require (
|
||||
golang.org/x/net v0.0.0-20190628185345-da137c7871d7
|
||||
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7 // indirect
|
||||
golang.org/x/time v0.0.0-20190513212739-9d24e82272b4 // indirect
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b
|
||||
google.golang.org/appengine v1.6.1 // indirect
|
||||
google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610
|
||||
google.golang.org/grpc v1.22.0
|
||||
|
49
go.sum
49
go.sum
@ -4,16 +4,20 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213609-cbe66965904d h1:VWP4o43LuzNbykZJzMUv5b9DWLgn0sn3GUj3RUyWMMQ=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213609-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/aristanetworks/goarista v0.0.0-20190712234253-ed1100a1c015 h1:7ABPr1+uJdqESAdlVevnc/2FJGiC/K3uMg1JiELeF+0=
|
||||
github.com/aristanetworks/goarista v0.0.0-20190712234253-ed1100a1c015/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190531201743-edce55837238 h1:uNljlOxtOHrPnRoPPx+JanqjAGZpNiqAGVBfGskd/pg=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190531201743-edce55837238/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM=
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
@ -21,14 +25,18 @@ github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf h1:CAKfRE2YtTUIjjh1bkBt
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d h1:SwD98825d6bdB+pEuTxWOXiSjBrHdOl/UVp75eI7JT8=
|
||||
github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8=
|
||||
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 h1:iwZdTE0PVqJCos1vaoKsclOGD3ADKpshg3SRtYBbwso=
|
||||
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
|
||||
github.com/cznic/strutil v0.0.0-20181122101858-275e90344537 h1:MZRmHqDBd0vxNwenEbKSQqRVT24d3C05ft8kduSwlqM=
|
||||
github.com/cznic/strutil v0.0.0-20181122101858-275e90344537/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4 h1:qk/FSDDxo05wdJH28W+p5yivv7LuLYLRXPPD8KQCtZs=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
@ -43,6 +51,7 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
|
||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
||||
github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc=
|
||||
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
|
||||
@ -57,10 +66,13 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 h1:ZgQEtGgCBiWRM39fZuwSd1LwSqqSW0hOdXCYYDX0R3I=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.3.1 h1:qGJ6qTW+x6xX/my+8YUVl4WNpX9B7+/l2tRsHGZ7f2s=
|
||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
@ -68,33 +80,47 @@ github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4 h1:z53tR0945TRRQO/fLEVPI6SMv7ZflF0TEaTAoU7tOzg=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.4.1/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.4 h1:5xLhQjsk4zqPf9EHCrja2qFZMx+yBqkO3XgJ14bNnU0=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.4/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.0.0/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
|
||||
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
|
||||
@ -109,7 +135,9 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.0/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/montanaflynn/stats v0.5.0 h1:2EkzeTSqBB4V4bJwWrt5gIIrZmpJBcoIRGS2kWLgzmk=
|
||||
github.com/montanaflynn/stats v0.5.0/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
@ -121,6 +149,10 @@ github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/openzipkin/zipkin-go v0.2.1 h1:noL5/5Uf1HpVl3wNsfkZhIKbSWCVi5jgqkONNx8PXcA=
|
||||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||
github.com/otokaze/mock v0.0.0-20190125081256-8282b7a7c7c3 h1:zjmNboC3QFuMdJSaZJ7Qvi3HUxWXPdj7wb3rc4jH5HI=
|
||||
github.com/otokaze/mock v0.0.0-20190125081256-8282b7a7c7c3/go.mod h1:pLR8n2aimFxvvDJ6n8JuQWthMGezCYMjuhlaTjPTZf0=
|
||||
github.com/otokaze/mock v1.1.1 h1:mQSWY25OMRIdBBuJO3AJ5CZ77WK6QtY0leU4qKGj4ok=
|
||||
github.com/otokaze/mock v1.1.1/go.mod h1:pLR8n2aimFxvvDJ6n8JuQWthMGezCYMjuhlaTjPTZf0=
|
||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
@ -147,6 +179,7 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
|
||||
github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE=
|
||||
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20190806203942-babf20351dd7e3ac320adedbbe5eb311aec8763c h1:eED6LswgZ3TfAl9fb+L2TfdSlXpYdg21iWZMdHuoSks=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20190806203942-babf20351dd7e3ac320adedbbe5eb311aec8763c/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec h1:6ncX5ko6B9LntYM0YBRXkiSaZMmLYeZ/NWcmeB43mMY=
|
||||
@ -160,8 +193,14 @@ github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjM
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8=
|
||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@ -170,12 +209,15 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tsuna/gohbase v0.0.0-20190502052937-24ffed0537aa h1:V/ABqiqsgqmpoIcLDSpJ1KqPfbxRmkcfET5+BRy9ctM=
|
||||
github.com/tsuna/gohbase v0.0.0-20190502052937-24ffed0537aa/go.mod h1:3HfLQly3YNLGxNv/2YOfmz30vcjG9hbuME1GpxoLlGs=
|
||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/etcd v0.0.0-20190720005121-fe86a786a4c3 h1:LlCFU/KJ9P/8QKB73kkd1z/zbm7ZJ2V4HEgEHI3N7gk=
|
||||
go.etcd.io/etcd v0.0.0-20190720005121-fe86a786a4c3/go.mod h1:N0RPWo9FXJYZQI4BTkDtQylrstIigYHeR18ONnyTufk=
|
||||
@ -191,6 +233,7 @@ golang.org/x/crypto v0.0.0-20180608092829-8ac0e0d97ce4/go.mod h1:6SG95UA2DQfeDnf
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
|
||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@ -236,11 +279,14 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b h1:mSUCVIwDx4hfXJfWsOPfdzEHxzb2Xjl6BQ8YgPnazQA=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.6.1 h1:QzqyMA1tlu6CgqCDUtU9V+ZKhLFT2dkJuANu5QaxI3I=
|
||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||
google.golang.org/genproto v0.0.0-20180608181217-32ee49c4dd80/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
@ -254,10 +300,12 @@ google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyac
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||
gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc=
|
||||
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
||||
@ -269,4 +317,5 @@ gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
|
4
pkg/testing/lich/README.md
Normal file
4
pkg/testing/lich/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
## testing/lich 运行环境构建
|
||||
基于 docker-compose 实现跨平台跨语言环境的容器依赖管理方案,以解决运行ut场景下的 (mysql, redis, mc)容器依赖问题。
|
||||
|
||||
使用说明参见:https://github.com/bilibili/kratos/tree/master/tool/testcli/README.md
|
130
pkg/testing/lich/composer.go
Normal file
130
pkg/testing/lich/composer.go
Normal file
@ -0,0 +1,130 @@
|
||||
package lich
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/md5"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
retry int
|
||||
yamlPath string
|
||||
pathHash string
|
||||
services map[string]*Container
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&yamlPath, "f", "docker-compose.yaml", "composer yaml path.")
|
||||
}
|
||||
|
||||
// Setup setup UT related environment dependence for everything.
|
||||
func Setup() (err error) {
|
||||
if _, err = os.Stat(yamlPath); os.IsNotExist(err) {
|
||||
log.Println("composer yaml is not exist!", yamlPath)
|
||||
return
|
||||
}
|
||||
if yamlPath, err = filepath.Abs(yamlPath); err != nil {
|
||||
log.Printf("filepath.Abs(%s) error(%v)", yamlPath, err)
|
||||
return
|
||||
}
|
||||
pathHash = fmt.Sprintf("%x", md5.Sum([]byte(yamlPath)))[:9]
|
||||
var args = []string{"-f", yamlPath, "-p", pathHash, "up", "-d"}
|
||||
if err = exec.Command("docker-compose", args...).Run(); err != nil {
|
||||
log.Printf("exec.Command(docker-composer) args(%v) error(%v)", args, err)
|
||||
Teardown()
|
||||
return
|
||||
}
|
||||
// 拿到yaml文件中的服务名,同时通过服务名获取到启动的容器ID
|
||||
if _, err = getServices(); err != nil {
|
||||
Teardown()
|
||||
return
|
||||
}
|
||||
// 通过容器ID检测容器的状态,包括容器服务的状态
|
||||
if _, err = checkServices(); err != nil {
|
||||
Teardown()
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Teardown unsetup all environment dependence.
|
||||
func Teardown() (err error) {
|
||||
if _, err = os.Stat(yamlPath); os.IsNotExist(err) {
|
||||
log.Println("composer yaml is not exist!")
|
||||
return
|
||||
}
|
||||
if yamlPath, err = filepath.Abs(yamlPath); err != nil {
|
||||
log.Printf("filepath.Abs(%s) error(%v)", yamlPath, err)
|
||||
return
|
||||
}
|
||||
pathHash = fmt.Sprintf("%x", md5.Sum([]byte(yamlPath)))[:9]
|
||||
args := []string{"-f", yamlPath, "-p", pathHash, "down"}
|
||||
if output, err := exec.Command("docker-compose", args...).CombinedOutput(); err != nil {
|
||||
log.Fatalf("exec.Command(docker-composer) args(%v) stdout(%s) error(%v)", args, string(output), err)
|
||||
return err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getServices() (output []byte, err error) {
|
||||
var args = []string{"-f", yamlPath, "-p", pathHash, "config", "--services"}
|
||||
if output, err = exec.Command("docker-compose", args...).CombinedOutput(); err != nil {
|
||||
log.Printf("exec.Command(docker-composer) args(%v) stdout(%s) error(%v)", args, string(output), err)
|
||||
return
|
||||
}
|
||||
services = make(map[string]*Container)
|
||||
output = bytes.TrimSpace(output)
|
||||
for _, svr := range bytes.Split(output, []byte("\n")) {
|
||||
args = []string{"-f", yamlPath, "-p", pathHash, "ps", "-a", "-q", string(svr)}
|
||||
if output, err = exec.Command("docker-compose", args...).CombinedOutput(); err != nil {
|
||||
log.Printf("exec.Command(docker-composer) args(%v) stdout(%s) error(%v)", args, string(output), err)
|
||||
return
|
||||
}
|
||||
var id = string(bytes.TrimSpace(output))
|
||||
args = []string{"inspect", id, "--format", "'{{json .}}'"}
|
||||
if output, err = exec.Command("docker", args...).CombinedOutput(); err != nil {
|
||||
log.Printf("exec.Command(docker) args(%v) stdout(%s) error(%v)", args, string(output), err)
|
||||
return
|
||||
}
|
||||
if output = bytes.TrimSpace(output); bytes.Equal(output, []byte("")) {
|
||||
err = fmt.Errorf("service: %s | container: %s fails to launch", svr, id)
|
||||
log.Printf("exec.Command(docker) args(%v) error(%v)", args, err)
|
||||
return
|
||||
}
|
||||
var c = &Container{}
|
||||
if err = json.Unmarshal(bytes.Trim(output, "'"), c); err != nil {
|
||||
log.Printf("json.Unmarshal(%s) error(%v)", string(output), err)
|
||||
return
|
||||
}
|
||||
services[string(svr)] = c
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func checkServices() (output []byte, err error) {
|
||||
defer func() {
|
||||
if err != nil && retry < 4 {
|
||||
retry++
|
||||
getServices()
|
||||
time.Sleep(time.Second * 5)
|
||||
output, err = checkServices()
|
||||
return
|
||||
}
|
||||
retry = 0
|
||||
}()
|
||||
for svr, c := range services {
|
||||
if err = c.Healthcheck(); err != nil {
|
||||
log.Printf("healthcheck(%s) error(%v) retrying %d times...", svr, err, 5-retry)
|
||||
return
|
||||
}
|
||||
// TODO About container check and more...
|
||||
}
|
||||
return
|
||||
}
|
23
pkg/testing/lich/composer_test.go
Normal file
23
pkg/testing/lich/composer_test.go
Normal file
@ -0,0 +1,23 @@
|
||||
package lich
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestComposer(t *testing.T) {
|
||||
convey.Convey("Composer testing....", t, func(convCtx convey.C) {
|
||||
convCtx.Convey("When Setup everything goes positive", func(convCtx convey.C) {
|
||||
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
|
||||
convCtx.So(Setup(), convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
|
||||
convCtx.Convey("When UnSetup everything goes positive", func(convCtx convey.C) {
|
||||
convCtx.Convey("Then err should be nil.", func(convCtx convey.C) {
|
||||
convCtx.So(Teardown(), convey.ShouldBeNil)
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
25
pkg/testing/lich/docker-compose.yaml
Normal file
25
pkg/testing/lich/docker-compose.yaml
Normal file
@ -0,0 +1,25 @@
|
||||
version: "3.7"
|
||||
|
||||
services:
|
||||
db:
|
||||
image: mysql:5.6
|
||||
ports:
|
||||
- 3306:3306
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=root
|
||||
volumes:
|
||||
- .:/docker-entrypoint-initdb.d
|
||||
command: [
|
||||
'--character-set-server=utf8',
|
||||
'--collation-server=utf8_unicode_ci'
|
||||
]
|
||||
|
||||
redis:
|
||||
image: redis
|
||||
ports:
|
||||
- 6379:6379
|
||||
|
||||
memcached:
|
||||
image: memcached
|
||||
ports:
|
||||
- 11211:11211
|
85
pkg/testing/lich/healthcheck.go
Normal file
85
pkg/testing/lich/healthcheck.go
Normal file
@ -0,0 +1,85 @@
|
||||
package lich
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"database/sql"
|
||||
// Register go-sql-driver stuff
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
)
|
||||
|
||||
var healthchecks = map[string]func(*Container) error{"mysql": checkMysql, "mariadb": checkMysql}
|
||||
|
||||
// Healthcheck check container health.
|
||||
func (c *Container) Healthcheck() (err error) {
|
||||
if status, health := c.State.Status, c.State.Health.Status; !c.State.Running || (health != "" && health != "healthy") {
|
||||
err = fmt.Errorf("service: %s | container: %s not running", c.GetImage(), c.GetID())
|
||||
log.Printf("docker status(%s) health(%s) error(%v)", status, health, err)
|
||||
return
|
||||
}
|
||||
if check, ok := healthchecks[c.GetImage()]; ok {
|
||||
err = check(c)
|
||||
return
|
||||
}
|
||||
for proto, ports := range c.NetworkSettings.Ports {
|
||||
if id := c.GetID(); !strings.Contains(proto, "tcp") {
|
||||
log.Printf("container: %s proto(%s) unsupported.", id, proto)
|
||||
continue
|
||||
}
|
||||
for _, pulish := range ports {
|
||||
var (
|
||||
ip = net.ParseIP(pulish.HostIP)
|
||||
port, _ = strconv.Atoi(pulish.HostPort)
|
||||
tcpAddr = &net.TCPAddr{IP: ip, Port: port}
|
||||
tcpConn *net.TCPConn
|
||||
)
|
||||
if tcpConn, err = net.DialTCP("tcp", nil, tcpAddr); err != nil {
|
||||
log.Printf("net.DialTCP(%s:%s) error(%v)", pulish.HostIP, pulish.HostPort, err)
|
||||
return
|
||||
}
|
||||
tcpConn.Close()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func checkMysql(c *Container) (err error) {
|
||||
var ip, port, user, passwd string
|
||||
for _, env := range c.Config.Env {
|
||||
splits := strings.Split(env, "=")
|
||||
if strings.Contains(splits[0], "MYSQL_ROOT_PASSWORD") {
|
||||
user, passwd = "root", splits[1]
|
||||
continue
|
||||
}
|
||||
if strings.Contains(splits[0], "MYSQL_ALLOW_EMPTY_PASSWORD") {
|
||||
user, passwd = "root", ""
|
||||
continue
|
||||
}
|
||||
if strings.Contains(splits[0], "MYSQL_USER") {
|
||||
user = splits[1]
|
||||
continue
|
||||
}
|
||||
if strings.Contains(splits[0], "MYSQL_PASSWORD") {
|
||||
passwd = splits[1]
|
||||
continue
|
||||
}
|
||||
}
|
||||
var db *sql.DB
|
||||
if ports, ok := c.NetworkSettings.Ports["3306/tcp"]; ok {
|
||||
ip, port = ports[0].HostIP, ports[0].HostPort
|
||||
}
|
||||
var dsn = fmt.Sprintf("%s:%s@tcp(%s:%s)/", user, passwd, ip, port)
|
||||
if db, err = sql.Open("mysql", dsn); err != nil {
|
||||
log.Printf("sql.Open(mysql) dsn(%s) error(%v)", dsn, err)
|
||||
return
|
||||
}
|
||||
if err = db.Ping(); err != nil {
|
||||
log.Printf("ping(db) dsn(%s) error(%v)", dsn, err)
|
||||
}
|
||||
defer db.Close()
|
||||
return
|
||||
}
|
88
pkg/testing/lich/model.go
Normal file
88
pkg/testing/lich/model.go
Normal file
@ -0,0 +1,88 @@
|
||||
package lich
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Container docker inspect resp.
|
||||
type Container struct {
|
||||
ID string `json:"Id"`
|
||||
Created time.Time `json:"Created"`
|
||||
Path string `json:"Path"`
|
||||
Args []string `json:"Args"`
|
||||
State struct {
|
||||
Status string `json:"Status"`
|
||||
Running bool `json:"Running"`
|
||||
Paused bool `json:"Paused"`
|
||||
Restarting bool `json:"Restarting"`
|
||||
OOMKilled bool `json:"OOMKilled"`
|
||||
Dead bool `json:"Dead"`
|
||||
Pid int `json:"Pid"`
|
||||
ExitCode int `json:"ExitCode"`
|
||||
Error string `json:"Error"`
|
||||
StartedAt time.Time `json:"StartedAt"`
|
||||
FinishedAt time.Time `json:"FinishedAt"`
|
||||
Health struct {
|
||||
Status string `json:"Status"`
|
||||
FailingStreak int `json:"FailingStreak"`
|
||||
Log []struct {
|
||||
Start time.Time `json:"Start"`
|
||||
End time.Time `json:"End"`
|
||||
ExitCode int `json:"ExitCode"`
|
||||
Output string `json:"Output"`
|
||||
} `json:"Log"`
|
||||
} `json:"Health"`
|
||||
} `json:"State"`
|
||||
Config struct {
|
||||
Hostname string `json:"Hostname"`
|
||||
Domainname string `json:"Domainname"`
|
||||
User string `json:"User"`
|
||||
Tty bool `json:"Tty"`
|
||||
OpenStdin bool `json:"OpenStdin"`
|
||||
StdinOnce bool `json:"StdinOnce"`
|
||||
Env []string `json:"Env"`
|
||||
Cmd []string `json:"Cmd"`
|
||||
Image string `json:"Image"`
|
||||
WorkingDir string `json:"WorkingDir"`
|
||||
Entrypoint []string `json:"Entrypoint"`
|
||||
} `json:"Config"`
|
||||
Image string `json:"Image"`
|
||||
ResolvConfPath string `json:"ResolvConfPath"`
|
||||
HostnamePath string `json:"HostnamePath"`
|
||||
HostsPath string `json:"HostsPath"`
|
||||
LogPath string `json:"LogPath"`
|
||||
Name string `json:"Name"`
|
||||
RestartCount int `json:"RestartCount"`
|
||||
Driver string `json:"Driver"`
|
||||
Platform string `json:"Platform"`
|
||||
MountLabel string `json:"MountLabel"`
|
||||
ProcessLabel string `json:"ProcessLabel"`
|
||||
AppArmorProfile string `json:"AppArmorProfile"`
|
||||
NetworkSettings struct {
|
||||
Bridge string `json:"Bridge"`
|
||||
SandboxID string `json:"SandboxID"`
|
||||
HairpinMode bool `json:"HairpinMode"`
|
||||
Ports map[string][]struct {
|
||||
HostIP string `json:"HostIp"`
|
||||
HostPort string `json:"HostPort"`
|
||||
} `json:"Ports"`
|
||||
} `json:"NetworkSettings"`
|
||||
}
|
||||
|
||||
// GetImage get image name at container
|
||||
func (c *Container) GetImage() (image string) {
|
||||
image = c.Config.Image
|
||||
if images := strings.Split(image, ":"); len(images) > 0 {
|
||||
image = images[0]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetID get id at container
|
||||
func (c *Container) GetID() (id string) {
|
||||
if id = c.ID; len(id) > 9 {
|
||||
id = id[0:9]
|
||||
}
|
||||
return
|
||||
}
|
154
tool/testcli/README.MD
Normal file
154
tool/testcli/README.MD
Normal file
@ -0,0 +1,154 @@
|
||||
## testcli UT运行环境构建工具
|
||||
基于 docker-compose 实现跨平台跨语言环境的容器依赖管理方案,以解决运行ut场景下的 (mysql, redis, mc)容器依赖问题。
|
||||
|
||||
*这个是testing/lich的二进制工具版本(Go请直接使用库版本:github.com/bilibili/kratos/pkg/testing/lich)*
|
||||
|
||||
### 功能和特性
|
||||
- 自动读取 test 目录下的 yaml 并启动依赖
|
||||
- 自动导入 test 目录下的 DB 初始化 SQL
|
||||
- 提供特定容器内的 healthcheck (mysql, mc, redis)
|
||||
- 提供一站式解决 UT 服务依赖的工具版本 (testcli)
|
||||
|
||||
### 编译安装
|
||||
*使用本工具/库需要前置安装好 docker&docker-compose*
|
||||
|
||||
#### Method 1. With go get
|
||||
```shell
|
||||
go get -u github.com/bilibili/kratos/tool/testcli
|
||||
$GOPATH/bin/testcli -h
|
||||
```
|
||||
#### Method 2. Build with Go
|
||||
```shell
|
||||
cd github.com/bilibili/kratos/tool/testcli
|
||||
go build -o $GOPATH/bin/testcli
|
||||
$GOPATH/bin/testcli -h
|
||||
```
|
||||
#### Method 3. Import with Kratos pkg
|
||||
```Go
|
||||
import "github.com/bilibili/kratos/pkg/testing/lich"
|
||||
```
|
||||
|
||||
### 构建数据
|
||||
#### Step 1. create docker-compose.yml
|
||||
创建依赖服务的 docker-compose.yml,并把它放在项目路径下的 test 文件夹下面。例如:
|
||||
```shell
|
||||
mkdir -p $YOUR_PROJECT/test
|
||||
```
|
||||
```yaml
|
||||
version: "3.7"
|
||||
|
||||
services:
|
||||
db:
|
||||
image: mysql:5.6
|
||||
ports:
|
||||
- 3306:3306
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=root
|
||||
volumes:
|
||||
- .:/docker-entrypoint-initdb.d
|
||||
command: [
|
||||
'--character-set-server=utf8',
|
||||
'--collation-server=utf8_unicode_ci'
|
||||
]
|
||||
|
||||
redis:
|
||||
image: redis
|
||||
ports:
|
||||
- 6379:6379
|
||||
```
|
||||
一般来讲,我们推荐在项目根目录创建 test 目录,里面存放描述服务的yml,以及需要初始化的数据(database.sql等)。
|
||||
|
||||
同时也需要注意,正确的对容器内服务进行健康检测,testcli会在容器的health状态执行UT,其实我们也内置了针对几个较为通用镜像(mysql mariadb mc redis)的健康检测,也就是不写也没事(^^;;
|
||||
|
||||
#### Step 2. export database.sql
|
||||
构造初始化的数据(database.sql等),当然也把它也在 test 文件夹里。
|
||||
```sql
|
||||
CREATE DATABASE IF NOT EXISTS `YOUR_DATABASE_NAME`;
|
||||
|
||||
SET NAMES 'utf8';
|
||||
USE `YOUR_DATABASE_NAME`;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `YOUR_TABLE_NAME` (
|
||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||
PRIMARY KEY (`id`),
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='YOUR_TABLE_NAME';
|
||||
```
|
||||
这里需要注意,在创建库/表的时候尽量加上 IF NOT EXISTS,以给予一定程度的容错,以及 SET NAMES 'utf8'; 用于解决客户端连接乱码问题。
|
||||
|
||||
#### Step 3. change your project mysql config
|
||||
```toml
|
||||
[mysql]
|
||||
addr = "127.0.0.1:3306"
|
||||
dsn = "root:root@tcp(127.0.0.1:3306)/YOUR_DATABASE?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8mb4,utf8"
|
||||
active = 20
|
||||
idle = 10
|
||||
idleTimeout ="1s"
|
||||
queryTimeout = "1s"
|
||||
execTimeout = "1s"
|
||||
tranTimeout = "1s"
|
||||
```
|
||||
在 *Step 1* 我们以及指定了服务对外暴露的端口为3306(这当然也可以是你指定的任何值),那理所应当的我们也要修改项目连接数据库的配置~
|
||||
|
||||
Great! 至此你已经完成了运行所需要用到的数据配置,接下来就来运行它。
|
||||
|
||||
### 运行
|
||||
开头也说过本工具支持两种运行方式:testcli 二进制工具版本和 go package 源码包,业务方可以根据需求场景进行选择。
|
||||
#### Method 1. With testcli tool
|
||||
*已支持的 flag: -f,--nodown,down,run*
|
||||
- -f,指定 docker-compose.yaml 文件路径,默认为当前目录下。
|
||||
- --nodown,指定是否在UT执行完成后保留容器,以供下次复用。
|
||||
- down,teardown 销毁当前项目下这个 compose 文件产生的容器。
|
||||
- run,运行你当前语言的单测执行命令(如:golang为 go test -v ./)
|
||||
|
||||
example:
|
||||
```shell
|
||||
testcli -f ../../test/docker-compose.yaml run go test -v ./
|
||||
```
|
||||
#### Method 2. Import with Kratos pkg
|
||||
- Step1. 在 Dao|Service 层中的 TestMain 单测主入口中,import "go-common/library/testing/lich" 引入testcli工具的go库版本。
|
||||
- Step2. 使用 flag.Set("f", "../../test/docker-compose.yaml") 指定 docker-compose.yaml 文件的路径。
|
||||
- Step3. 在 flag.Parse() 后即可使用 lich.Setup() 安装依赖&初始化数据(注意测试用例执行结束后 lich.Teardown() 回收下~)
|
||||
- Step4. 运行 `go test -v ./ `看看效果吧~
|
||||
example:
|
||||
```Go
|
||||
package dao
|
||||
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/bilibili/kratos/pkg/conf/paladin"
|
||||
"github.com/bilibili/kratos/pkg/testing/lich"
|
||||
)
|
||||
|
||||
var (
|
||||
d *Dao
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
flag.Set("conf", "../../configs")
|
||||
flag.Set("f", "../../test/docker-compose.yaml")
|
||||
flag.Parse()
|
||||
if err := paladin.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := lich.Setup(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer lich.Teardown()
|
||||
d = New()
|
||||
if code := m.Run(); code != 0 {
|
||||
lich.Teardown()
|
||||
os.Exit(code)
|
||||
}
|
||||
}
|
||||
```
|
||||
## 注意
|
||||
因为启动mysql容器较为缓慢,健康检测的机制会重试3次,每次暂留5秒钟,基本在10s内mysql就能从creating到服务正常启动!
|
||||
|
||||
当然你也可以在使用 testcli 时加上 --nodown,使其不用每次跑都新建容器,只在第一次跑的时候会初始化容器,后面都进行复用,这样速度会快很多。
|
||||
|
||||
成功启动后就欢乐奔放的玩耍吧~ Good Lucky!
|
60
tool/testcli/main.go
Normal file
60
tool/testcli/main.go
Normal file
@ -0,0 +1,60 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/bilibili/kratos/pkg/testing/lich"
|
||||
)
|
||||
|
||||
var (
|
||||
noDown bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.BoolVar(&noDown, "nodown", false, "containers are not recycled.")
|
||||
}
|
||||
|
||||
func parseArgs() (flags map[string]string) {
|
||||
flags = make(map[string]string)
|
||||
for idx, arg := range os.Args {
|
||||
if idx == 0 {
|
||||
continue
|
||||
}
|
||||
if arg == "down" {
|
||||
flags["down"] = ""
|
||||
return
|
||||
}
|
||||
if cmds := os.Args[idx+1:]; arg == "run" {
|
||||
flags["run"] = strings.Join(cmds, " ")
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
flags := parseArgs()
|
||||
if _, ok := flags["down"]; ok {
|
||||
lich.Teardown()
|
||||
return
|
||||
}
|
||||
if cmd, ok := flags["run"]; !ok || cmd == "" {
|
||||
panic("Your need 'run' flag assign to be run commands.")
|
||||
}
|
||||
if err := lich.Setup(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if !noDown {
|
||||
defer lich.Teardown()
|
||||
}
|
||||
cmds := strings.Split(flags["run"], " ")
|
||||
cmd := exec.Command(cmds[0], cmds[1:]...)
|
||||
cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
52
tool/testgen/README.md
Normal file
52
tool/testgen/README.md
Normal file
@ -0,0 +1,52 @@
|
||||
## testgen UT代码自动生成器
|
||||
解放你的双手,让你的UT一步到位!
|
||||
|
||||
### 功能和特性
|
||||
- 支持生成 Dao|Service 层UT代码功能(每个方法包含一个正向用例)
|
||||
- 支持生成 Dao|Service 层测试入口文件dao_test.go, service_test.go(用于控制初始化,控制测试流程等)
|
||||
- 支持生成Mock代码(使用GoMock框架)
|
||||
- 支持选择不同模式生成不同代码(使用"–m mode"指定)
|
||||
- 生成单元测试代码时,同时支持传入目录或文件
|
||||
- 支持指定方法追加生成测试用例(使用"–func funcName"指定)
|
||||
|
||||
### 编译安装
|
||||
#### Method 1. With go get
|
||||
```shell
|
||||
go get -u github.com/bilibili/kratos/tool/testgen
|
||||
$GOPATH/bin/testgen -h
|
||||
```
|
||||
#### Method 2. Build with Go
|
||||
```shell
|
||||
cd github.com/bilibili/kratos/tool/testgen
|
||||
go build -o $GOPATH/bin/testgen
|
||||
$GOPATH/bin/testgen -h
|
||||
```
|
||||
### 运行
|
||||
#### 生成Dao/Service层单元UT
|
||||
```shell
|
||||
$GOPATH/bin/testgen YOUR_PROJECT/dao # default mode
|
||||
$GOPATH/bin/testgen --m test path/to/your/pkg
|
||||
$GOPATH/bin/testgen --func functionName path/to/your/pkg
|
||||
```
|
||||
|
||||
#### 生成接口类型
|
||||
```shell
|
||||
$GOPATH/bin/testgen --m interface YOUR_PROJECT/dao #当前仅支持传目录,如目录包含子目录也会做处理
|
||||
```
|
||||
|
||||
#### 生成Mock代码
|
||||
```shell
|
||||
$GOPATH/bin/testgen --m mock YOUR_PROJECT/dao #仅传入包路径即可
|
||||
```
|
||||
|
||||
#### 生成Monkey代码
|
||||
```shell
|
||||
$GOPATH/bin/testgen --m monkey yourCodeDirPath #仅传入包路径即可
|
||||
```
|
||||
### 赋诗一首
|
||||
```
|
||||
莫生气 莫生气
|
||||
代码辣鸡非我意
|
||||
自己动手分田地
|
||||
谈笑风生活长命
|
||||
```
|
419
tool/testgen/gen.go
Normal file
419
tool/testgen/gen.go
Normal file
@ -0,0 +1,419 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/otokaze/mock/mockgen"
|
||||
"github.com/otokaze/mock/mockgen/model"
|
||||
)
|
||||
|
||||
func genTest(parses []*parse) (err error) {
|
||||
for _, p := range parses {
|
||||
switch {
|
||||
case strings.HasSuffix(p.Path, "_mock.go") ||
|
||||
strings.HasSuffix(p.Path, ".intf.go"):
|
||||
continue
|
||||
case strings.HasSuffix(p.Path, "dao.go") ||
|
||||
strings.HasSuffix(p.Path, "service.go"):
|
||||
err = p.genTestMain()
|
||||
default:
|
||||
err = p.genUTTest()
|
||||
}
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *parse) genUTTest() (err error) {
|
||||
var (
|
||||
buffer bytes.Buffer
|
||||
impts = strings.Join([]string{
|
||||
`"context"`,
|
||||
`"testing"`,
|
||||
`. "github.com/smartystreets/goconvey/convey"`,
|
||||
}, "\n\t")
|
||||
content []byte
|
||||
)
|
||||
filename := strings.Replace(p.Path, ".go", "_test.go", -1)
|
||||
if _, err = os.Stat(filename); (_func == "" && err == nil) ||
|
||||
(err != nil && os.IsExist(err)) {
|
||||
err = nil
|
||||
return
|
||||
}
|
||||
for _, impt := range p.Imports {
|
||||
impts += "\n\t\"" + impt.V + "\""
|
||||
}
|
||||
if _func == "" {
|
||||
buffer.WriteString(fmt.Sprintf(tpPackage, p.Package))
|
||||
buffer.WriteString(fmt.Sprintf(tpImport, impts))
|
||||
}
|
||||
for _, parseFunc := range p.Funcs {
|
||||
if _func != "" && _func != parseFunc.Name {
|
||||
continue
|
||||
}
|
||||
var (
|
||||
methodK string
|
||||
tpVars string
|
||||
vars []string
|
||||
val []string
|
||||
notice = "Then "
|
||||
reset string
|
||||
)
|
||||
if method := ConvertMethod(p.Path); method != "" {
|
||||
methodK = method + "."
|
||||
}
|
||||
tpTestFuncs := fmt.Sprintf(tpTestFunc, strings.Title(p.Package), parseFunc.Name, "", parseFunc.Name, "%s", "%s", "%s")
|
||||
tpTestFuncBeCall := methodK + parseFunc.Name + "(%s)\n\t\t\tConvey(\"%s\", func() {"
|
||||
if parseFunc.Result == nil {
|
||||
tpTestFuncBeCall = fmt.Sprintf(tpTestFuncBeCall, "%s", "No return values")
|
||||
tpTestFuncs = fmt.Sprintf(tpTestFuncs, "%s", tpTestFuncBeCall, "%s")
|
||||
}
|
||||
for k, res := range parseFunc.Result {
|
||||
if res.K == "" {
|
||||
res.K = fmt.Sprintf("p%d", k+1)
|
||||
}
|
||||
var so string
|
||||
if res.V == "error" {
|
||||
res.K = "err"
|
||||
so = fmt.Sprintf("\tSo(%s, ShouldBeNil)", res.K)
|
||||
notice += "err should be nil."
|
||||
} else {
|
||||
so = fmt.Sprintf("\tSo(%s, ShouldNotBeNil)", res.K)
|
||||
val = append(val, res.K)
|
||||
}
|
||||
if len(parseFunc.Result) <= k+1 {
|
||||
if len(val) != 0 {
|
||||
notice += strings.Join(val, ",") + " should not be nil."
|
||||
}
|
||||
tpTestFuncBeCall = fmt.Sprintf(tpTestFuncBeCall, "%s", notice)
|
||||
res.K += " := " + tpTestFuncBeCall
|
||||
} else {
|
||||
res.K += ", %s"
|
||||
}
|
||||
tpTestFuncs = fmt.Sprintf(tpTestFuncs, "%s", res.K+"\n\t\t\t%s", "%s")
|
||||
tpTestFuncs = fmt.Sprintf(tpTestFuncs, "%s", "%s", so, "%s")
|
||||
}
|
||||
if parseFunc.Params == nil {
|
||||
tpTestFuncs = fmt.Sprintf(tpTestFuncs, "%s", "", "%s")
|
||||
}
|
||||
for k, pType := range parseFunc.Params {
|
||||
if pType.K == "" {
|
||||
pType.K = fmt.Sprintf("a%d", k+1)
|
||||
}
|
||||
var (
|
||||
init string
|
||||
params = pType.K
|
||||
)
|
||||
switch {
|
||||
case strings.HasPrefix(pType.V, "context"):
|
||||
init = params + " = context.Background()"
|
||||
case strings.HasPrefix(pType.V, "[]byte"):
|
||||
init = params + " = " + pType.V + "(\"\")"
|
||||
case strings.HasPrefix(pType.V, "[]"):
|
||||
init = params + " = " + pType.V + "{}"
|
||||
case strings.HasPrefix(pType.V, "int") ||
|
||||
strings.HasPrefix(pType.V, "uint") ||
|
||||
strings.HasPrefix(pType.V, "float") ||
|
||||
strings.HasPrefix(pType.V, "double"):
|
||||
init = params + " = " + pType.V + "(0)"
|
||||
case strings.HasPrefix(pType.V, "string"):
|
||||
init = params + " = \"\""
|
||||
case strings.Contains(pType.V, "*xsql.Tx"):
|
||||
init = params + ",_ = " + methodK + "BeginTran(c)"
|
||||
reset += "\n\t" + params + ".Commit()"
|
||||
case strings.HasPrefix(pType.V, "*"):
|
||||
init = params + " = " + strings.Replace(pType.V, "*", "&", -1) + "{}"
|
||||
case strings.Contains(pType.V, "chan"):
|
||||
init = params + " = " + pType.V
|
||||
case pType.V == "time.Time":
|
||||
init = params + " = time.Now()"
|
||||
case strings.Contains(pType.V, "chan"):
|
||||
init = params + " = " + pType.V
|
||||
default:
|
||||
init = params + " " + pType.V
|
||||
}
|
||||
vars = append(vars, "\t\t"+init)
|
||||
if len(parseFunc.Params) > k+1 {
|
||||
params += ", %s"
|
||||
}
|
||||
tpTestFuncs = fmt.Sprintf(tpTestFuncs, "%s", params, "%s")
|
||||
}
|
||||
if len(vars) > 0 {
|
||||
tpVars = fmt.Sprintf(tpVar, strings.Join(vars, "\n\t"))
|
||||
}
|
||||
tpTestFuncs = fmt.Sprintf(tpTestFuncs, tpVars, "%s")
|
||||
if reset != "" {
|
||||
tpTestResets := fmt.Sprintf(tpTestReset, reset)
|
||||
tpTestFuncs = fmt.Sprintf(tpTestFuncs, tpTestResets)
|
||||
} else {
|
||||
tpTestFuncs = fmt.Sprintf(tpTestFuncs, "")
|
||||
}
|
||||
buffer.WriteString(tpTestFuncs)
|
||||
}
|
||||
var (
|
||||
file *os.File
|
||||
flag = os.O_RDWR | os.O_CREATE | os.O_APPEND
|
||||
)
|
||||
if file, err = os.OpenFile(filename, flag, 0644); err != nil {
|
||||
return
|
||||
}
|
||||
if _func == "" {
|
||||
content, _ = GoImport(filename, buffer.Bytes())
|
||||
} else {
|
||||
content = buffer.Bytes()
|
||||
}
|
||||
if _, err = file.Write(content); err != nil {
|
||||
return
|
||||
}
|
||||
if err = file.Close(); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *parse) genTestMain() (err error) {
|
||||
var (
|
||||
new bool
|
||||
buffer bytes.Buffer
|
||||
impts string
|
||||
vars, mainFunc string
|
||||
content []byte
|
||||
instance, confFunc string
|
||||
tomlPath = "**PUT PATH TO YOUR CONFIG FILES HERE**"
|
||||
filename = strings.Replace(p.Path, ".go", "_test.go", -1)
|
||||
)
|
||||
if p.Imports["paladin"] != nil {
|
||||
new = true
|
||||
}
|
||||
// if _intfMode {
|
||||
// imptsList = append(imptsList, `"github.com/golang/mock/gomock"`)
|
||||
// for _, field := range p.Structs {
|
||||
// var hit bool
|
||||
// pkgName := strings.Split(field.V, ".")[0]
|
||||
// interfaceName := strings.Split(field.V, ".")[1]
|
||||
// if p.Imports[pkgName] != nil {
|
||||
// if hit, err = checkInterfaceMock(strings.Split(field.V, ".")[1], p.Imports[pkgName].V); err != nil {
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
// if hit {
|
||||
// imptsList = append(imptsList, "mock"+p.Imports[pkgName].K+" \""+p.Imports[pkgName].V+"/mock\"")
|
||||
// pkgName = "mock" + strings.Title(pkgName)
|
||||
// interfaceName = "Mock" + interfaceName
|
||||
// varsList = append(varsList, "mock"+strings.Title(field.K)+" *"+pkgName+"."+interfaceName)
|
||||
// mockStmt += "\tmock" + strings.Title(field.K) + " = " + pkgName + ".New" + interfaceName + "(mockCtrl)\n"
|
||||
// newStmt += "\t\t" + field.K + ":\tmock" + strings.Title(field.K) + ",\n"
|
||||
// } else {
|
||||
// pkgName = subString(field.V, "*", ".")
|
||||
// if p.Imports[pkgName] != nil && pkgName != "conf" {
|
||||
// imptsList = append(imptsList, p.Imports[pkgName].K+" \""+p.Imports[pkgName].V+"\"")
|
||||
// }
|
||||
// switch {
|
||||
// case strings.HasPrefix(field.V, "*conf."):
|
||||
// newStmt += "\t\t" + field.K + ":\tconf.Conf,\n"
|
||||
// case strings.HasPrefix(field.V, "*"):
|
||||
// newStmt += "\t\t" + field.K + ":\t" + strings.Replace(field.V, "*", "&", -1) + "{},\n"
|
||||
// default:
|
||||
// newStmt += "\t\t" + field.K + ":\t" + field.V + ",\n"
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// mockStmt = fmt.Sprintf(_tpTestServiceMainMockStmt, mockStmt)
|
||||
// newStmt = fmt.Sprintf(_tpTestServiceMainNewStmt, newStmt)
|
||||
// }
|
||||
if instance = ConvertMethod(p.Path); instance == "s" {
|
||||
vars = strings.Join([]string{"s *Service"}, "\n\t")
|
||||
mainFunc = tpTestServiceMain
|
||||
} else {
|
||||
vars = strings.Join([]string{"d *Dao"}, "\n\t")
|
||||
mainFunc = tpTestDaoMain
|
||||
}
|
||||
if new {
|
||||
impts = strings.Join([]string{`"os"`, `"flag"`, `"testing"`, p.Imports["paladin"].V}, "\n\t")
|
||||
confFunc = fmt.Sprintf(tpTestMainNew, instance+" = New()")
|
||||
} else {
|
||||
impts = strings.Join(append([]string{`"os"`, `"flag"`, `"testing"`}), "\n\t")
|
||||
confFunc = fmt.Sprintf(tpTestMainOld, instance+" = New(conf.Conf)")
|
||||
}
|
||||
if _, err := os.Stat(filename); os.IsNotExist(err) {
|
||||
buffer.WriteString(fmt.Sprintf(tpPackage, p.Package))
|
||||
buffer.WriteString(fmt.Sprintf(tpImport, impts))
|
||||
buffer.WriteString(fmt.Sprintf(tpVar, vars))
|
||||
buffer.WriteString(fmt.Sprintf(mainFunc, tomlPath, confFunc))
|
||||
content, _ = GoImport(filename, buffer.Bytes())
|
||||
ioutil.WriteFile(filename, content, 0644)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func genInterface(parses []*parse) (err error) {
|
||||
var (
|
||||
parse *parse
|
||||
pkg = make(map[string]string)
|
||||
)
|
||||
for _, parse = range parses {
|
||||
if strings.Contains(parse.Path, ".intf.go") {
|
||||
continue
|
||||
}
|
||||
dirPath := filepath.Dir(parse.Path)
|
||||
for _, parseFunc := range parse.Funcs {
|
||||
if (parseFunc.Method == nil) ||
|
||||
!(parseFunc.Name[0] >= 'A' && parseFunc.Name[0] <= 'Z') {
|
||||
continue
|
||||
}
|
||||
var (
|
||||
params string
|
||||
results string
|
||||
)
|
||||
for k, param := range parseFunc.Params {
|
||||
params += param.K + " " + param.P + param.V
|
||||
if len(parseFunc.Params) > k+1 {
|
||||
params += ", "
|
||||
}
|
||||
}
|
||||
for k, res := range parseFunc.Result {
|
||||
results += res.K + " " + res.P + res.V
|
||||
if len(parseFunc.Result) > k+1 {
|
||||
results += ", "
|
||||
}
|
||||
}
|
||||
if len(results) != 0 {
|
||||
results = "(" + results + ")"
|
||||
}
|
||||
pkg[dirPath] += "\t" + fmt.Sprintf(tpIntfcFunc, parseFunc.Name, params, results)
|
||||
}
|
||||
}
|
||||
for k, v := range pkg {
|
||||
var buffer bytes.Buffer
|
||||
pathSplit := strings.Split(k, "/")
|
||||
filename := k + "/" + pathSplit[len(pathSplit)-1] + ".intf.go"
|
||||
if _, exist := os.Stat(filename); os.IsExist(exist) {
|
||||
continue
|
||||
}
|
||||
buffer.WriteString(fmt.Sprintf(tpPackage, pathSplit[len(pathSplit)-1]))
|
||||
buffer.WriteString(fmt.Sprintf(tpInterface, strings.Title(pathSplit[len(pathSplit)-1]), v))
|
||||
content, _ := GoImport(filename, buffer.Bytes())
|
||||
err = ioutil.WriteFile(filename, content, 0644)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func genMock(files ...string) (err error) {
|
||||
for _, file := range files {
|
||||
var pkg *model.Package
|
||||
if pkg, err = mockgen.ParseFile(file); err != nil {
|
||||
return
|
||||
}
|
||||
if len(pkg.Interfaces) == 0 {
|
||||
continue
|
||||
}
|
||||
var mockDir = pkg.SrcDir + "/mock"
|
||||
if _, err = os.Stat(mockDir); os.IsNotExist(err) {
|
||||
err = nil
|
||||
os.Mkdir(mockDir, 0744)
|
||||
}
|
||||
var mockPath = mockDir + "/" + pkg.Name + "_mock.go"
|
||||
if _, exist := os.Stat(mockPath); os.IsExist(exist) {
|
||||
continue
|
||||
}
|
||||
var g = &mockgen.Generator{Filename: file}
|
||||
if err = g.Generate(pkg, "mock", mockPath); err != nil {
|
||||
return
|
||||
}
|
||||
if err = ioutil.WriteFile(mockPath, g.Output(), 0644); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func genMonkey(parses []*parse) (err error) {
|
||||
var (
|
||||
pkg = make(map[string]string)
|
||||
)
|
||||
for _, parse := range parses {
|
||||
if strings.Contains(parse.Path, "monkey.go") ||
|
||||
strings.Contains(parse.Path, "/mock/") {
|
||||
continue
|
||||
}
|
||||
var (
|
||||
path = strings.Split(filepath.Dir(parse.Path), "/")
|
||||
pack = ConvertHump(path[len(path)-1])
|
||||
refer = path[len(path)-1]
|
||||
mockVar, mockType, srcDir string
|
||||
)
|
||||
for i := len(path) - 1; i > len(path)-4; i-- {
|
||||
if path[i] == "dao" || path[i] == "service" {
|
||||
srcDir = strings.Join(path[:i+1], "/")
|
||||
break
|
||||
}
|
||||
pack = ConvertHump(path[i-1]) + pack
|
||||
}
|
||||
if mockVar = ConvertMethod(parse.Path); mockType == "d" {
|
||||
mockType = "*" + refer + ".Dao"
|
||||
} else {
|
||||
mockType = "*" + refer + ".Service"
|
||||
}
|
||||
for _, parseFunc := range parse.Funcs {
|
||||
if (parseFunc.Method == nil) || (parseFunc.Result == nil) ||
|
||||
!(parseFunc.Name[0] >= 'A' && parseFunc.Name[0] <= 'Z') {
|
||||
continue
|
||||
}
|
||||
var (
|
||||
funcParams, funcResults, mockKey, mockValue, funcName string
|
||||
)
|
||||
funcName = pack + parseFunc.Name
|
||||
for k, param := range parseFunc.Params {
|
||||
funcParams += "_ " + param.V
|
||||
if len(parseFunc.Params) > k+1 {
|
||||
funcParams += ", "
|
||||
}
|
||||
}
|
||||
for k, res := range parseFunc.Result {
|
||||
if res.K == "" {
|
||||
if res.V == "error" {
|
||||
res.K = "err"
|
||||
} else {
|
||||
res.K = fmt.Sprintf("p%d", k+1)
|
||||
}
|
||||
}
|
||||
mockKey += res.K
|
||||
mockValue += res.V
|
||||
funcResults += res.K + " " + res.P + res.V
|
||||
if len(parseFunc.Result) > k+1 {
|
||||
mockKey += ", "
|
||||
mockValue += ", "
|
||||
funcResults += ", "
|
||||
}
|
||||
}
|
||||
pkg[srcDir+"."+refer] += fmt.Sprintf(tpMonkeyFunc, funcName, funcName, mockVar, mockType, funcResults, mockVar, parseFunc.Name, mockType, funcParams, mockValue, mockKey)
|
||||
}
|
||||
}
|
||||
for path, content := range pkg {
|
||||
var (
|
||||
buffer bytes.Buffer
|
||||
dir = strings.Split(path, ".")
|
||||
mockDir = dir[0] + "/mock"
|
||||
filename = mockDir + "/monkey_" + dir[1] + ".go"
|
||||
)
|
||||
if _, err = os.Stat(mockDir); os.IsNotExist(err) {
|
||||
err = nil
|
||||
os.Mkdir(mockDir, 0744)
|
||||
}
|
||||
if _, err := os.Stat(filename); os.IsExist(err) {
|
||||
continue
|
||||
}
|
||||
buffer.WriteString(fmt.Sprintf(tpPackage, "mock"))
|
||||
buffer.WriteString(content)
|
||||
content, _ := GoImport(filename, buffer.Bytes())
|
||||
ioutil.WriteFile(filename, content, 0644)
|
||||
}
|
||||
return
|
||||
}
|
57
tool/testgen/main.go
Normal file
57
tool/testgen/main.go
Normal file
@ -0,0 +1,57 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
var (
|
||||
err error
|
||||
_mode, _func string
|
||||
files []string
|
||||
parses []*parse
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.StringVar(&_mode, "m", "test", "Generating code by Working mode. [test|interface|mock...]")
|
||||
flag.StringVar(&_func, "func", "", "Generating code by function.")
|
||||
flag.Parse()
|
||||
if len(os.Args) == 1 {
|
||||
println("Creater is a tool for generating code.\n\nUsage: creater [-m]")
|
||||
flag.PrintDefaults()
|
||||
return
|
||||
}
|
||||
if err = parseArgs(os.Args[1:], &files, 0); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
switch _mode {
|
||||
case "monkey":
|
||||
if parses, err = parseFile(files...); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err = genMonkey(parses); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
case "test":
|
||||
if parses, err = parseFile(files...); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err = genTest(parses); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
case "interface":
|
||||
if parses, err = parseFile(files...); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err = genInterface(parses); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
case "mock":
|
||||
if err = genMock(files...); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
default:
|
||||
}
|
||||
fmt.Println(print)
|
||||
}
|
193
tool/testgen/parser.go
Normal file
193
tool/testgen/parser.go
Normal file
@ -0,0 +1,193 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type param struct{ K, V, P string }
|
||||
|
||||
type parse struct {
|
||||
Path string
|
||||
Package string
|
||||
// Imports []string
|
||||
Imports map[string]*param
|
||||
// Structs []*param
|
||||
// Interfaces []string
|
||||
Funcs []*struct {
|
||||
Name string
|
||||
Method, Params, Result []*param
|
||||
}
|
||||
}
|
||||
|
||||
func parseArgs(args []string, res *[]string, index int) (err error) {
|
||||
if len(args) <= index {
|
||||
return
|
||||
}
|
||||
if strings.HasPrefix(args[index], "-") {
|
||||
index += 2
|
||||
parseArgs(args, res, index)
|
||||
return
|
||||
}
|
||||
var f os.FileInfo
|
||||
if f, err = os.Stat(args[index]); err != nil {
|
||||
return
|
||||
}
|
||||
if f.IsDir() {
|
||||
if !strings.HasSuffix(args[index], "/") {
|
||||
args[index] += "/"
|
||||
}
|
||||
var fs []os.FileInfo
|
||||
if fs, err = ioutil.ReadDir(args[index]); err != nil {
|
||||
return
|
||||
}
|
||||
for _, f = range fs {
|
||||
path, _ := filepath.Abs(args[index] + f.Name())
|
||||
args = append(args, path)
|
||||
}
|
||||
} else {
|
||||
if strings.HasSuffix(args[index], ".go") &&
|
||||
!strings.HasSuffix(args[index], "_test.go") {
|
||||
*res = append(*res, args[index])
|
||||
}
|
||||
}
|
||||
index++
|
||||
return parseArgs(args, res, index)
|
||||
}
|
||||
|
||||
func parseFile(files ...string) (parses []*parse, err error) {
|
||||
for _, file := range files {
|
||||
var (
|
||||
astFile *ast.File
|
||||
fSet = token.NewFileSet()
|
||||
parse = &parse{
|
||||
Imports: make(map[string]*param),
|
||||
}
|
||||
)
|
||||
if astFile, err = parser.ParseFile(fSet, file, nil, 0); err != nil {
|
||||
return
|
||||
}
|
||||
if astFile.Name != nil {
|
||||
parse.Path = file
|
||||
parse.Package = astFile.Name.Name
|
||||
}
|
||||
for _, decl := range astFile.Decls {
|
||||
switch decl.(type) {
|
||||
case *ast.GenDecl:
|
||||
if specs := decl.(*ast.GenDecl).Specs; len(specs) > 0 {
|
||||
parse.Imports = parseImports(specs)
|
||||
}
|
||||
case *ast.FuncDecl:
|
||||
var (
|
||||
dec = decl.(*ast.FuncDecl)
|
||||
parseFunc = &struct {
|
||||
Name string
|
||||
Method, Params, Result []*param
|
||||
}{Name: dec.Name.Name}
|
||||
)
|
||||
if dec.Recv != nil {
|
||||
parseFunc.Method = parserParams(dec.Recv.List)
|
||||
}
|
||||
if dec.Type.Params != nil {
|
||||
parseFunc.Params = parserParams(dec.Type.Params.List)
|
||||
}
|
||||
if dec.Type.Results != nil {
|
||||
parseFunc.Result = parserParams(dec.Type.Results.List)
|
||||
}
|
||||
parse.Funcs = append(parse.Funcs, parseFunc)
|
||||
}
|
||||
}
|
||||
parses = append(parses, parse)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parserParams(fields []*ast.Field) (params []*param) {
|
||||
for _, field := range fields {
|
||||
p := ¶m{}
|
||||
p.V = parseType(field.Type)
|
||||
if field.Names == nil {
|
||||
params = append(params, p)
|
||||
}
|
||||
for _, name := range field.Names {
|
||||
sp := ¶m{}
|
||||
sp.K = name.Name
|
||||
sp.V = p.V
|
||||
sp.P = p.P
|
||||
params = append(params, sp)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func parseType(expr ast.Expr) string {
|
||||
switch expr.(type) {
|
||||
case *ast.Ident:
|
||||
return expr.(*ast.Ident).Name
|
||||
case *ast.StarExpr:
|
||||
return "*" + parseType(expr.(*ast.StarExpr).X)
|
||||
case *ast.ArrayType:
|
||||
return "[" + parseType(expr.(*ast.ArrayType).Len) + "]" + parseType(expr.(*ast.ArrayType).Elt)
|
||||
case *ast.SelectorExpr:
|
||||
return parseType(expr.(*ast.SelectorExpr).X) + "." + expr.(*ast.SelectorExpr).Sel.Name
|
||||
case *ast.MapType:
|
||||
return "map[" + parseType(expr.(*ast.MapType).Key) + "]" + parseType(expr.(*ast.MapType).Value)
|
||||
case *ast.StructType:
|
||||
return "struct{}"
|
||||
case *ast.InterfaceType:
|
||||
return "interface{}"
|
||||
case *ast.FuncType:
|
||||
var (
|
||||
pTemp string
|
||||
rTemp string
|
||||
)
|
||||
pTemp = parseFuncType(pTemp, expr.(*ast.FuncType).Params)
|
||||
if expr.(*ast.FuncType).Results != nil {
|
||||
rTemp = parseFuncType(rTemp, expr.(*ast.FuncType).Results)
|
||||
return fmt.Sprintf("func(%s) (%s)", pTemp, rTemp)
|
||||
}
|
||||
return fmt.Sprintf("func(%s)", pTemp)
|
||||
case *ast.ChanType:
|
||||
return fmt.Sprintf("make(chan %s)", parseType(expr.(*ast.ChanType).Value))
|
||||
case *ast.Ellipsis:
|
||||
return parseType(expr.(*ast.Ellipsis).Elt)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func parseFuncType(temp string, data *ast.FieldList) string {
|
||||
var params = parserParams(data.List)
|
||||
for i, param := range params {
|
||||
if i == 0 {
|
||||
temp = param.K + " " + param.V
|
||||
continue
|
||||
}
|
||||
t := param.K + " " + param.V
|
||||
temp = fmt.Sprintf("%s, %s", temp, t)
|
||||
}
|
||||
return temp
|
||||
}
|
||||
|
||||
func parseImports(specs []ast.Spec) (params map[string]*param) {
|
||||
params = make(map[string]*param)
|
||||
for _, spec := range specs {
|
||||
switch spec.(type) {
|
||||
case *ast.ImportSpec:
|
||||
p := ¶m{V: strings.Replace(spec.(*ast.ImportSpec).Path.Value, "\"", "", -1)}
|
||||
if spec.(*ast.ImportSpec).Name != nil {
|
||||
p.K = spec.(*ast.ImportSpec).Name.Name
|
||||
params[p.K] = p
|
||||
} else {
|
||||
vs := strings.Split(p.V, "/")
|
||||
params[vs[len(vs)-1]] = p
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
41
tool/testgen/templete.go
Normal file
41
tool/testgen/templete.go
Normal file
@ -0,0 +1,41 @@
|
||||
package main
|
||||
|
||||
var (
|
||||
tpPackage = "package %s\n\n"
|
||||
tpImport = "import (\n\t%s\n)\n\n"
|
||||
tpVar = "var (\n\t%s\n)\n"
|
||||
tpInterface = "type %sInterface interface {\n%s}\n"
|
||||
tpIntfcFunc = "%s(%s) %s\n"
|
||||
tpMonkeyFunc = "// Mock%s .\nfunc Mock%s(%s %s,%s) (guard *monkey.PatchGuard) {\n\treturn monkey.PatchInstanceMethod(reflect.TypeOf(%s), \"%s\", func(_ %s, %s) (%s) {\n\t\treturn %s\n\t})\n}\n\n"
|
||||
tpTestReset = "\n\t\tReset(func() {%s\n\t\t})"
|
||||
tpTestFunc = "func Test%s%s(t *testing.T){%s\n\tConvey(\"%s\", t, func(){\n\t\t%s\tConvey(\"When everything goes positive\", func(){\n\t\t\t%s\n\t\t\t})\n\t\t})%s\n\t})\n}\n\n"
|
||||
tpTestDaoMain = `func TestMain(m *testing.M) {
|
||||
flag.Set("conf", "%s")
|
||||
flag.Parse()
|
||||
%s
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
`
|
||||
tpTestServiceMain = `func TestMain(m *testing.M){
|
||||
flag.Set("conf", "%s")
|
||||
flag.Parse()
|
||||
%s
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
`
|
||||
tpTestMainNew = `if err := paladin.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
%s`
|
||||
tpTestMainOld = `if err := conf.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
%s`
|
||||
print = `Generation success!
|
||||
莫生气
|
||||
代码辣鸡非我意,
|
||||
自己动手分田地;
|
||||
你若气死谁如意?
|
||||
谈笑风生活长命.
|
||||
// Release 1.2.3. Powered by 主站质保团队`
|
||||
)
|
42
tool/testgen/utils.go
Normal file
42
tool/testgen/utils.go
Normal file
@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/imports"
|
||||
)
|
||||
|
||||
// GoImport Use golang.org/x/tools/imports auto import pkg
|
||||
func GoImport(file string, bytes []byte) (res []byte, err error) {
|
||||
options := &imports.Options{
|
||||
TabWidth: 8,
|
||||
TabIndent: true,
|
||||
Comments: true,
|
||||
Fragment: true,
|
||||
}
|
||||
if res, err = imports.Process(file, bytes, options); err != nil {
|
||||
fmt.Printf("GoImport(%s) error(%v)", file, err)
|
||||
res = bytes
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ConvertMethod checkout the file belongs to dao or not
|
||||
func ConvertMethod(path string) (method string) {
|
||||
switch {
|
||||
case strings.Contains(path, "/dao"):
|
||||
method = "d"
|
||||
case strings.Contains(path, "/service"):
|
||||
method = "s"
|
||||
default:
|
||||
method = ""
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//ConvertHump convert words to hump style
|
||||
func ConvertHump(words string) string {
|
||||
return strings.ToUpper(words[0:1]) + words[1:]
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user