diff --git a/go.mod b/go.mod
index 1763bafcf..b176cd9f1 100644
--- a/go.mod
+++ b/go.mod
@@ -44,14 +44,19 @@ require (
go.uber.org/mock v0.2.0
go.uber.org/multierr v1.11.0
go.uber.org/zap v1.24.0
- golang.org/x/crypto v0.10.0
+ golang.org/x/crypto v0.14.0
golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc
golang.org/x/time v0.3.0
- google.golang.org/grpc v1.56.1
+ google.golang.org/grpc v1.58.3
gorm.io/driver/mysql v1.4.6
gorm.io/gorm v1.24.5
)
+require (
+ google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
+)
+
require (
cosmossdk.io/api v0.4.0 // indirect
cosmossdk.io/core v0.6.1 // indirect
@@ -124,7 +129,7 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.3.0 // indirect
github.com/golang/glog v1.1.0 // indirect
- github.com/golang/mock v1.6.0 // indirect
+ github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.1.2 // indirect
@@ -275,14 +280,14 @@ require (
go.uber.org/fx v1.19.2 // indirect
golang.org/x/arch v0.5.0 // indirect
golang.org/x/mod v0.11.0 // indirect
- golang.org/x/net v0.11.0 // indirect
+ golang.org/x/net v0.17.0 // indirect
golang.org/x/sync v0.3.0 // indirect
- golang.org/x/sys v0.9.0 // indirect
- golang.org/x/term v0.9.0 // indirect
- golang.org/x/text v0.10.0 // indirect
+ golang.org/x/sys v0.13.0 // indirect
+ golang.org/x/term v0.13.0 // indirect
+ golang.org/x/text v0.13.0 // indirect
golang.org/x/tools v0.10.0 // indirect
- google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
- google.golang.org/protobuf v1.30.0 // indirect
+ google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 // indirect
+ google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
@@ -295,13 +300,13 @@ require (
)
replace (
- cosmossdk.io/api => github.com/bnb-chain/greenfield-cosmos-sdk/api v0.0.0-20230816082903-b48770f5e210
- cosmossdk.io/math => github.com/bnb-chain/greenfield-cosmos-sdk/math v0.0.0-20230816082903-b48770f5e210
+ cosmossdk.io/api => github.com/bnb-chain/greenfield-cosmos-sdk/api v0.0.0-20231129013257-1e407f209b02
+ cosmossdk.io/math => github.com/bnb-chain/greenfield-cosmos-sdk/math v0.0.0-20231129013257-1e407f209b02
github.com/btcsuite/btcd => github.com/btcsuite/btcd v0.23.0
github.com/cometbft/cometbft => github.com/bnb-chain/greenfield-cometbft v0.0.0-20231030090949-99ef7dbd1e62
github.com/cometbft/cometbft-db => github.com/bnb-chain/greenfield-cometbft-db v0.8.1-alpha.1
github.com/confio/ics23/go => github.com/cosmos/cosmos-sdk/ics23/go v0.8.0
- github.com/cosmos/cosmos-sdk => github.com/bnb-chain/greenfield-cosmos-sdk v1.0.2-0.20231101023808-a3c24a58eca0
+ github.com/cosmos/cosmos-sdk => github.com/bnb-chain/greenfield-cosmos-sdk v1.0.2-0.20231129013257-1e407f209b02
github.com/cosmos/iavl => github.com/bnb-chain/greenfield-iavl v0.20.1
github.com/forbole/juno/v4 => github.com/bnb-chain/juno/v4 v4.0.0-20231027060606-82070b5da95a
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
diff --git a/go.sum b/go.sum
index 1362b6bf2..f304f7fe8 100644
--- a/go.sum
+++ b/go.sum
@@ -184,12 +184,12 @@ github.com/bnb-chain/greenfield-cometbft-db v0.8.1-alpha.1 h1:XcWulGacHVRiSCx90Q
github.com/bnb-chain/greenfield-cometbft-db v0.8.1-alpha.1/go.mod h1:ey1CiK4bYo1RBNJLRiVbYr5CMdSxci9S/AZRINLtppI=
github.com/bnb-chain/greenfield-common/go v0.0.0-20230906132736-eb2f0efea228 h1:WywBaew30hZuqDTOQbkRV3uBg6XHjNIE1s3AXVXbG+8=
github.com/bnb-chain/greenfield-common/go v0.0.0-20230906132736-eb2f0efea228/go.mod h1:K9jK80fbahciC+FAvrch8Qsbw9ZkvVgjfKsqrzPTAVA=
-github.com/bnb-chain/greenfield-cosmos-sdk v1.0.2-0.20231101023808-a3c24a58eca0 h1:5BQrQRqQ0GTR3UgvTtlTCJAYPkWrjk9Yk9kRnmzzut0=
-github.com/bnb-chain/greenfield-cosmos-sdk v1.0.2-0.20231101023808-a3c24a58eca0/go.mod h1:ZWyfWX032fdHkICmEoJwylfqmL+Atf/QNVS8GzJq1Kc=
-github.com/bnb-chain/greenfield-cosmos-sdk/api v0.0.0-20230816082903-b48770f5e210 h1:GHPbV2bC+gmuO6/sG0Tm8oGal3KKSRlyE+zPscDjlA8=
-github.com/bnb-chain/greenfield-cosmos-sdk/api v0.0.0-20230816082903-b48770f5e210/go.mod h1:vhsZxXE9tYJeYB5JR4hPhd6Pc/uPf7j1T8IJ7p9FdeM=
-github.com/bnb-chain/greenfield-cosmos-sdk/math v0.0.0-20230816082903-b48770f5e210 h1:FLVOn4+OVbsKi2+YJX5kmD27/4dRu4FW7xCXFhzDO5s=
-github.com/bnb-chain/greenfield-cosmos-sdk/math v0.0.0-20230816082903-b48770f5e210/go.mod h1:An0MllWJY6PxibUpnwGk8jOm+a/qIxlKmL5Zyp9NnaM=
+github.com/bnb-chain/greenfield-cosmos-sdk v1.0.2-0.20231129013257-1e407f209b02 h1:x9F+rt7H4VOS4JfoqMFFvq3RGW27oSxIFPTI/cMK4tQ=
+github.com/bnb-chain/greenfield-cosmos-sdk v1.0.2-0.20231129013257-1e407f209b02/go.mod h1:Yrvq+J1Lsm7OHFX+M/AZWBTGt1TRHUTC4VYOMlvW3fs=
+github.com/bnb-chain/greenfield-cosmos-sdk/api v0.0.0-20231129013257-1e407f209b02 h1:cwuShQ+MlvwkfbOz79BRF4aYjgKAuSyugoCtXE8tWgM=
+github.com/bnb-chain/greenfield-cosmos-sdk/api v0.0.0-20231129013257-1e407f209b02/go.mod h1:vhsZxXE9tYJeYB5JR4hPhd6Pc/uPf7j1T8IJ7p9FdeM=
+github.com/bnb-chain/greenfield-cosmos-sdk/math v0.0.0-20231129013257-1e407f209b02 h1:RMrZep7e2dcMk4E5YysMdCn6PekI3vA2WHfnMQ/kg18=
+github.com/bnb-chain/greenfield-cosmos-sdk/math v0.0.0-20231129013257-1e407f209b02/go.mod h1:An0MllWJY6PxibUpnwGk8jOm+a/qIxlKmL5Zyp9NnaM=
github.com/bnb-chain/greenfield-iavl v0.20.1 h1:y3L64GU99otNp27/xLVBTDbv4eroR6CzoYz0rbaVotM=
github.com/bnb-chain/greenfield-iavl v0.20.1/go.mod h1:oLksTs8dfh7DYIKBro7hbRQ+ewls7ghJ27pIXlbEXyI=
github.com/bnb-chain/juno/v4 v4.0.0-20231027060606-82070b5da95a h1:fEv/SCzaoumMqfY6OcP4ksXR2L0D8DPbIXPfXdXiODg=
@@ -1734,8 +1734,8 @@ golang.org/x/crypto v0.0.0-20211117183948-ae814b36b871/go.mod h1:IxCIyHEi3zRg3s0
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
-golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
-golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
+golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -1851,8 +1851,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
-golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
+golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20170912212905-13449ad91cb2/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -2001,16 +2001,16 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
-golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28=
-golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
+golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
+golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -2025,8 +2025,8 @@ golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
-golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -2203,8 +2203,12 @@ google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210426193834-eac7f76ac494/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
-google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
-google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
+google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g=
+google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0=
+google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw=
+google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
google.golang.org/grpc v1.2.1-0.20170921194603-d4b75ebd4f9f/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
@@ -2238,8 +2242,8 @@ google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
-google.golang.org/grpc v1.56.1 h1:z0dNfjIl0VpaZ9iSVjA6daGatAYwPGstTjt5vkRMFkQ=
-google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
+google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ=
+google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/grpc/examples v0.0.0-20200723182653-9106c3fff523/go.mod h1:5j1uub0jRGhRiSghIlrThmBUgcgLXOVJQ/l1getT4uo=
google.golang.org/grpc/examples v0.0.0-20210424002626-9572fd6faeae/go.mod h1:Ly7ZA/ARzg8fnPU9TyZIxoz33sEUuWX7txiqs8lPTgE=
@@ -2257,8 +2261,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
-google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
+google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610=
gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI=
diff --git a/modular/gater/metadata_handler.go b/modular/gater/metadata_handler.go
index 97c81e6cf..38e9c8ab9 100644
--- a/modular/gater/metadata_handler.go
+++ b/modular/gater/metadata_handler.go
@@ -4,10 +4,8 @@ import (
"bytes"
"encoding/base64"
"encoding/xml"
- "fmt"
"net/http"
"net/url"
- "regexp"
"strconv"
"strings"
"time"
@@ -118,8 +116,6 @@ func (g *GateModular) getUserBucketsHandler(w http.ResponseWriter, r *http.Reque
return
}
- respBytes = processVGFInfoBucketXmlResponse(respBytes, grpcResponse.Buckets)
-
w.Header().Set(ContentTypeHeader, ContentTypeXMLHeaderValue)
w.Write(respBytes)
}
@@ -278,13 +274,12 @@ func (g *GateModular) listObjectsByBucketNameHandler(w http.ResponseWriter, r *h
}
respBytes, err = xml.Marshal(grpcResponse)
+
if err != nil {
- log.CtxErrorw(reqCtx.Context(), "failed to get user buckets", "error", err)
+ log.CtxErrorw(reqCtx.Context(), "failed to list objects by given bucket name", "error", err)
return
}
- respBytes = processObjectsXmlResponse(respBytes, grpcResponse.Objects)
-
w.Header().Set(ContentTypeHeader, ContentTypeXMLHeaderValue)
w.Write(respBytes)
}
@@ -335,16 +330,13 @@ func (g *GateModular) getObjectMetaHandler(w http.ResponseWriter, r *http.Reques
grpcResponse := &types.GfSpGetObjectMetaResponse{
Object: resp,
}
-
respBytes, err = xml.Marshal(grpcResponse)
+
if err != nil {
log.Errorf("failed to get object meta", "error", err)
return
}
- var objects = []*types.Object{grpcResponse.Object}
- respBytes = processObjectsXmlResponse(respBytes, objects)
-
w.Header().Set(ContentTypeHeader, ContentTypeXMLHeaderValue)
w.Write(respBytes)
}
@@ -395,9 +387,6 @@ func (g *GateModular) getBucketMetaHandler(w http.ResponseWriter, r *http.Reques
return
}
- var bucketsWithPayment = []*types.GfSpGetBucketMetaResponse{grpcResponse}
- respBytes = processBucketsWithPaymentResponse(respBytes, bucketsWithPayment)
-
w.Header().Set(ContentTypeHeader, ContentTypeXMLHeaderValue)
w.Write(respBytes)
}
@@ -587,36 +576,10 @@ func (g *GateModular) getGroupListHandler(w http.ResponseWriter, r *http.Request
return
}
- respBytes = processGroupsXmlResponse(respBytes, grpcResponse.Groups)
-
w.Header().Set(ContentTypeHeader, ContentTypeXMLHeaderValue)
w.Write(respBytes)
}
-type GfSpListObjectsByIDsResponse types.GfSpListObjectsByIDsResponse
-
-type ObjectEntry struct {
- Id uint64
- Value *types.Object
-}
-
-func (m GfSpListObjectsByIDsResponse) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
- if len(m.Objects) == 0 {
- return nil
- }
-
- err := e.EncodeToken(start)
- if err != nil {
- return err
- }
-
- for k, v := range m.Objects {
- e.Encode(ObjectEntry{Id: k, Value: v})
- }
-
- return e.EncodeToken(start.End())
-}
-
// listObjectsByIDsHandler list objects by object ids
func (g *GateModular) listObjectsByIDsHandler(w http.ResponseWriter, r *http.Request) {
var (
@@ -663,7 +626,7 @@ func (g *GateModular) listObjectsByIDsHandler(w http.ResponseWriter, r *http.Req
}
if len(objectIDs) == 0 || len(objectIDs) > MaximumIDSize {
- log.Errorf("failed to check ids", "error", err)
+ log.Errorf("len(objectIDs) is invalid : %d", len(objectIDs))
err = ErrInvalidQuery
return
}
@@ -687,42 +650,16 @@ func (g *GateModular) listObjectsByIDsHandler(w http.ResponseWriter, r *http.Req
}
grpcResponse := &types.GfSpListObjectsByIDsResponse{Objects: objects}
- respBytes, err = xml.Marshal((*GfSpListObjectsByIDsResponse)(grpcResponse))
+ respBytes, err = xml.Marshal(grpcResponse)
if err != nil {
log.Errorf("failed to list objects by ids", "error", err)
return
}
- respBytes = processObjectsMapXmlResponse(respBytes, grpcResponse.Objects)
-
w.Header().Set(ContentTypeHeader, ContentTypeXMLHeaderValue)
w.Write(respBytes)
}
-type GfSpListBucketsByIDsResponse types.GfSpListBucketsByIDsResponse
-
-type BucketEntry struct {
- Id uint64
- Value *types.Bucket
-}
-
-func (m GfSpListBucketsByIDsResponse) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
- if len(m.Buckets) == 0 {
- return nil
- }
-
- err := e.EncodeToken(start)
- if err != nil {
- return err
- }
-
- for k, v := range m.Buckets {
- e.Encode(BucketEntry{Id: k, Value: v})
- }
-
- return e.EncodeToken(start.End())
-}
-
// listBucketsByIDsHandler list buckets by bucket ids
func (g *GateModular) listBucketsByIDsHandler(w http.ResponseWriter, r *http.Request) {
var (
@@ -793,14 +730,12 @@ func (g *GateModular) listBucketsByIDsHandler(w http.ResponseWriter, r *http.Req
}
grpcResponse := &types.GfSpListBucketsByIDsResponse{Buckets: buckets}
- respBytes, err = xml.Marshal((*GfSpListBucketsByIDsResponse)(grpcResponse))
+ respBytes, err = xml.Marshal(grpcResponse)
if err != nil {
log.Errorf("failed to list buckets by ids", "error", err)
return
}
- respBytes = processBucketsMapXmlResponse(respBytes, grpcResponse.Buckets)
-
w.Header().Set(ContentTypeHeader, ContentTypeXMLHeaderValue)
w.Write(respBytes)
}
@@ -2239,8 +2174,6 @@ func (g *GateModular) getUserGroupsHandler(w http.ResponseWriter, r *http.Reques
return
}
- respBytes = processGroupMembersXmlResponse(respBytes, grpcResponse.Groups)
-
w.Header().Set(ContentTypeHeader, ContentTypeXMLHeaderValue)
w.Write(respBytes)
}
@@ -2283,7 +2216,7 @@ func (g *GateModular) getGroupMembersHandler(w http.ResponseWriter, r *http.Requ
if requestStartAfter != "" {
if ok := common.IsHexAddress(requestStartAfter); !ok {
log.Errorw("failed to check start after", "start-after", requestStartAfter, "error", err)
- err = ErrInvalidHeader
+ err = ErrInvalidQuery
return
}
}
@@ -2316,8 +2249,6 @@ func (g *GateModular) getGroupMembersHandler(w http.ResponseWriter, r *http.Requ
return
}
- respBytes = processGroupMembersXmlResponse(respBytes, grpcResponse.Groups)
-
w.Header().Set(ContentTypeHeader, ContentTypeXMLHeaderValue)
w.Write(respBytes)
}
@@ -2391,8 +2322,6 @@ func (g *GateModular) getUserOwnedGroupsHandler(w http.ResponseWriter, r *http.R
return
}
- respBytes = processGroupMembersXmlResponse(respBytes, grpcResponse.Groups)
-
w.Header().Set(ContentTypeHeader, ContentTypeXMLHeaderValue)
w.Write(respBytes)
}
@@ -2522,7 +2451,7 @@ func (g *GateModular) listPaymentAccountStreamsHandler(w http.ResponseWriter, r
if ok := common.IsHexAddress(paymentAccount); !ok {
log.Errorw("failed to check payment account", "payment-account", paymentAccount, "error", err)
- err = ErrInvalidHeader
+ err = ErrInvalidQuery
return
}
@@ -2540,8 +2469,6 @@ func (g *GateModular) listPaymentAccountStreamsHandler(w http.ResponseWriter, r
return
}
- respBytes = processBucketsXmlResponse(respBytes, grpcResponse.Buckets)
-
w.Header().Set(ContentTypeHeader, ContentTypeXMLHeaderValue)
w.Write(respBytes)
}
@@ -2590,36 +2517,10 @@ func (g *GateModular) listUserPaymentAccountsHandler(w http.ResponseWriter, r *h
return
}
- respBytes = processPaymentResponse(respBytes, grpcResponse)
-
w.Header().Set(ContentTypeHeader, ContentTypeXMLHeaderValue)
w.Write(respBytes)
}
-type GfSpListGroupsByIDsResponse types.GfSpListGroupsByIDsResponse
-
-type GroupEntry struct {
- Id uint64
- Value *types.Group
-}
-
-func (m GfSpListGroupsByIDsResponse) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
- if len(m.Groups) == 0 {
- return nil
- }
-
- err := e.EncodeToken(start)
- if err != nil {
- return err
- }
-
- for k, v := range m.Groups {
- e.Encode(GroupEntry{Id: k, Value: v})
- }
-
- return e.EncodeToken(start.End())
-}
-
// listGroupsByIDsHandler list groups by ids
func (g *GateModular) listGroupsByIDsHandler(w http.ResponseWriter, r *http.Request) {
var (
@@ -2690,14 +2591,12 @@ func (g *GateModular) listGroupsByIDsHandler(w http.ResponseWriter, r *http.Requ
}
grpcResponse := &types.GfSpListGroupsByIDsResponse{Groups: groups}
- respBytes, err = xml.Marshal((*GfSpListGroupsByIDsResponse)(grpcResponse))
+ respBytes, err = xml.Marshal(grpcResponse)
if err != nil {
log.Errorf("failed to list groups by ids", "error", err)
return
}
- respBytes = processGroupsMapXmlResponse(respBytes, grpcResponse.Groups)
-
w.Header().Set(ContentTypeHeader, ContentTypeXMLHeaderValue)
w.Write(respBytes)
}
@@ -2881,170 +2780,3 @@ func (g *GateModular) getBucketSizeHandler(w http.ResponseWriter, r *http.Reques
w.Header().Set(ContentTypeHeader, ContentTypeXMLHeaderValue)
w.Write(respBytes)
}
-
-// processObjectsXmlResponse process the unhandled Uint id and checksum of object xml unmarshal
-func processObjectsXmlResponse(respBytes []byte, objects []*types.Object) (respBytesProcessed []byte) {
- respString := string(respBytes)
- // startIdx is to trace the index for next checkSum to be processed
- var startIdx = 0
- for _, object := range objects {
- if object != nil {
- // iterate through each object and assign id value
- respString = strings.Replace(respString, "", ""+object.ObjectInfo.Id.String()+"", 1)
- // inside each object, there is an array of checksum that need to be unmarshalled correctly
- for _, checkSum := range object.ObjectInfo.Checksums {
- re := regexp.MustCompile("(.*?)")
- // first find the matching string of regex
- found := re.FindString(respString[startIdx:])
- respCheckSum := "" + fmt.Sprintf("%x", checkSum) + ""
- if found != "" {
- // replace the matching string of regex and move the startIdx after that to search next regex
- respString = strings.Replace(respString, found, respCheckSum, 1)
- startIdx = strings.LastIndex(respString, respCheckSum) + len(respCheckSum)
- }
- }
- }
- }
- respBytesProcessed = []byte(respString)
- return
-}
-
-// processObjectsMapXmlResponse process the unhandled Uint id and checksum of object map xml unmarshal
-func processObjectsMapXmlResponse(respBytes []byte, objects map[uint64]*types.Object) (respBytesProcessed []byte) {
- respString := string(respBytes)
- // startIdx is to trace the index for next checkSum to be processed
- var startIdx = 0
- for _, object := range objects {
- if object != nil {
- // iterate through each object and assign id value
- respString = strings.Replace(respString, "", ""+object.ObjectInfo.Id.String()+"", 1)
- // inside each object, there is an array of checksum that need to be unmarshalled correctly
- for _, checkSum := range object.ObjectInfo.Checksums {
- re := regexp.MustCompile("(.*?)")
- // first find the matching string of regex
- found := re.FindString(respString[startIdx:])
- respCheckSum := "" + fmt.Sprintf("%x", checkSum) + ""
- if found != "" {
- // replace the matching string of regex and move the startIdx after that to search next regex
- respString = strings.Replace(respString, found, respCheckSum, 1)
- startIdx = strings.LastIndex(respString, respCheckSum) + len(respCheckSum)
- }
- }
- }
- }
- respBytesProcessed = []byte(respString)
- return
-}
-
-// processGroupsMapXmlResponse process the unhandled Uint id of group map xml unmarshal
-func processGroupsMapXmlResponse(respBytes []byte, groups map[uint64]*types.Group) (respBytesProcessed []byte) {
- respString := string(respBytes)
- for _, group := range groups {
- if group != nil {
- // iterate through each group and assign id value
- respString = strings.Replace(respString, "", ""+group.Group.Id.String()+"", 1)
- }
- }
- respBytesProcessed = []byte(respString)
- return
-}
-
-// processBucketsXmlResponse process the unhandled Uint id of bucket xml unmarshal
-func processBucketsXmlResponse(respBytes []byte, buckets []*types.Bucket) (respBytesProcessed []byte) {
- respString := string(respBytes)
- for _, bucket := range buckets {
- if bucket != nil {
- // iterate through each bucket and assign id value
- respString = strings.Replace(respString, "", ""+bucket.BucketInfo.Id.String()+"", 1)
- }
- }
- respBytesProcessed = []byte(respString)
- return
-}
-
-// processBucketsWithPaymentResponse process the unhandled Uint id and several balance of bucket with payment xml unmarshal
-func processBucketsWithPaymentResponse(respBytes []byte, buckets []*types.GfSpGetBucketMetaResponse) (respBytesProcessed []byte) {
- respString := string(respBytes)
- for _, bucket := range buckets {
- if bucket != nil {
- // iterate through each bucket and assign id and payment Uint value
- respString = strings.Replace(respString, "", ""+bucket.Bucket.BucketInfo.Id.String()+"", 1)
- respString = strings.Replace(respString, "", ""+bucket.StreamRecord.NetflowRate.String()+"", 1)
- respString = strings.Replace(respString, "", ""+bucket.StreamRecord.StaticBalance.String()+"", 1)
- respString = strings.Replace(respString, "", ""+bucket.StreamRecord.BufferBalance.String()+"", 1)
- respString = strings.Replace(respString, "", ""+bucket.StreamRecord.LockBalance.String()+"", 1)
- respString = strings.Replace(respString, "", ""+bucket.StreamRecord.FrozenNetflowRate.String()+"", 1)
- }
- }
- respBytesProcessed = []byte(respString)
- return
-}
-
-// processPaymentResponse process the unhandled Uint id and several balance of payment xml unmarshal
-func processPaymentResponse(respBytes []byte, payments *types.GfSpListUserPaymentAccountsResponse) (respBytesProcessed []byte) {
- respString := string(respBytes)
- for _, payment := range payments.PaymentAccounts {
- if payment != nil {
- // iterate through each payment Uint value
- respString = strings.Replace(respString, "", ""+payment.StreamRecord.NetflowRate.String()+"", 1)
- respString = strings.Replace(respString, "", ""+payment.StreamRecord.StaticBalance.String()+"", 1)
- respString = strings.Replace(respString, "", ""+payment.StreamRecord.BufferBalance.String()+"", 1)
- respString = strings.Replace(respString, "", ""+payment.StreamRecord.LockBalance.String()+"", 1)
- respString = strings.Replace(respString, "", ""+payment.StreamRecord.FrozenNetflowRate.String()+"", 1)
- }
- }
- respBytesProcessed = []byte(respString)
- return
-}
-
-// processBucketsMapXmlResponse process the unhandled Uint id of bucket map xml unmarshal
-func processBucketsMapXmlResponse(respBytes []byte, buckets map[uint64]*types.Bucket) (respBytesProcessed []byte) {
- respString := string(respBytes)
- for _, bucket := range buckets {
- if bucket != nil {
- // iterate through each bucket and assign id value
- respString = strings.Replace(respString, "", ""+bucket.BucketInfo.Id.String()+"", 1)
- }
- }
- respBytesProcessed = []byte(respString)
- return
-}
-
-// processGroupsXmlResponse process the unhandled Uint id of group xml unmarshal
-func processGroupsXmlResponse(respBytes []byte, groups []*types.Group) (respBytesProcessed []byte) {
- respString := string(respBytes)
- for _, group := range groups {
- if group != nil {
- // iterate through each group and assign id value
- respString = strings.Replace(respString, "", ""+group.Group.Id.String()+"", 1)
- }
- }
- respBytesProcessed = []byte(respString)
- return
-}
-
-// processGroupMembersXmlResponse process the unhandled Uint id of group member xml unmarshal
-func processGroupMembersXmlResponse(respBytes []byte, groupMembers []*types.GroupMember) (respBytesProcessed []byte) {
- respString := string(respBytes)
- for _, group := range groupMembers {
- if group != nil {
- // iterate through each group and assign id value
- respString = strings.Replace(respString, "", ""+group.Group.Id.String()+"", 1)
- }
- }
- respBytesProcessed = []byte(respString)
- return
-}
-
-// processVGFInfoBucketXmlResponse process the unhandled Uint id of bucket with vgf xml unmarshal
-func processVGFInfoBucketXmlResponse(respBytes []byte, buckets []*types.VGFInfoBucket) (respBytesProcessed []byte) {
- respString := string(respBytes)
- for _, bucket := range buckets {
- if bucket != nil {
- // iterate through each bucket and assign id value
- respString = strings.Replace(respString, "", ""+bucket.BucketInfo.Id.String()+"", 1)
- }
- }
- respBytesProcessed = []byte(respString)
- return
-}
diff --git a/modular/gater/metadata_handler_test.go b/modular/gater/metadata_handler_test.go
new file mode 100644
index 000000000..7cdc902af
--- /dev/null
+++ b/modular/gater/metadata_handler_test.go
@@ -0,0 +1,2084 @@
+package gater
+
+import (
+ "encoding/base64"
+ "encoding/xml"
+ "fmt"
+ "log"
+ "math/big"
+ "net/http"
+ "net/http/httptest"
+ "strconv"
+ "strings"
+ "testing"
+ "time"
+
+ "cosmossdk.io/math"
+ "github.com/gorilla/mux"
+ "github.com/stretchr/testify/assert"
+ "go.uber.org/mock/gomock"
+
+ "github.com/bnb-chain/greenfield-storage-provider/modular/metadata/types"
+ payment_types "github.com/bnb-chain/greenfield/x/payment/types"
+ storage_types "github.com/bnb-chain/greenfield/x/storage/types"
+ virtual_types "github.com/bnb-chain/greenfield/x/virtualgroup/types"
+
+ "github.com/bnb-chain/greenfield-storage-provider/base/gfspclient"
+)
+
+const (
+ testAccount = "0xF72aDa8130f934887755492879496b026665FbAB"
+)
+
+func mockListObjectsByBucketNameRoute(t *testing.T, g *GateModular) *mux.Router {
+ t.Helper()
+ router := mux.NewRouter().SkipClean(true)
+ var routers []*mux.Router
+ routers = append(routers, router.Host("{bucket:.+}."+g.domain).Subrouter())
+ routers = append(routers, router.PathPrefix("/{bucket}").Subrouter())
+ for _, r := range routers {
+ r.NewRoute().Name(listObjectsByBucketRouterName).Methods(http.MethodGet).Path("/").HandlerFunc(g.listObjectsByBucketNameHandler)
+
+ }
+ return router
+}
+
+func getSampleChecksum() [][]byte {
+ checksumsInBase64 := [7]string{"tPsLBcgLxRVKTRJCeYw5FVj0jjqPsqFnbDCr77pf7RA=",
+ "7YqCbwK/qC+zaAoJvd971fuJCE0OVQ9ky8bgomUkmRI=",
+ "i59qS3vgvN8QIcNKOJggtN4JsZRLYt1ugeGDtP6x7Sk=",
+ "tBBu4BPpANbc12SO5TVeQ64DtKwl0F2inE29H9jAw54=",
+ "vOw+loeUIXXPEvfYNFmnElTIxj/b0dEEBBF1YbKOoEI=",
+ "e0nSN4a5u3EDPaAqemGDZ5gYJ0l6NUjtalmj/BH2uWE=",
+ "rRm6iKPMc8gZbw1WKKF2kPXveU2VFEh2izs9e8ovfwk="}
+ checksums := make([][]byte, len(checksumsInBase64))
+ for j := 0; j < len(checksums); j++ {
+ checksums[j], _ = base64.StdEncoding.DecodeString(checksumsInBase64[j])
+ }
+ return checksums
+
+}
+func getTestGroupsInIdMap(length int) map[uint64]*types.Group {
+ groupsMap := make(map[uint64]*types.Group)
+ groups := getTestGroupsResponse(length)
+ for _, g := range groups {
+ groupsMap[g.Group.Id.BigInt().Uint64()] = g
+ }
+ return groupsMap
+}
+
+func getTestBucketsInIdMap(length int) map[uint64]*types.Bucket {
+ bucketsMap := make(map[uint64]*types.Bucket)
+ buckets := getTestBuckets(length)
+ for _, b := range buckets {
+ bucketsMap[b.BucketInfo.Id.BigInt().Uint64()] = b
+ }
+ return bucketsMap
+}
+
+func getTestBuckets(length int) []*types.Bucket {
+ buckets := make([]*types.Bucket, length)
+
+ for i := 0; i < length; i++ {
+ bucket := &types.Bucket{
+ BucketInfo: &storage_types.BucketInfo{
+ Owner: testAccount,
+ BucketName: mockBucketName + strconv.Itoa(i),
+ Visibility: storage_types.VISIBILITY_TYPE_PUBLIC_READ,
+ Id: math.NewUintFromBigInt(big.NewInt(int64(i))),
+ SourceType: storage_types.SOURCE_TYPE_ORIGIN,
+ CreateAt: 1699781080,
+ PaymentAddress: testAccount,
+ GlobalVirtualGroupFamilyId: 3,
+ ChargedReadQuota: 0,
+ BucketStatus: storage_types.BUCKET_STATUS_CREATED,
+ },
+ Removed: false,
+ DeleteAt: 0,
+ DeleteReason: "",
+ Operator: testAccount,
+ CreateTxHash: "0x21c349a869bde1f44378936e2a9a15ed3fb2d54a43eaea8787960bba1134cdc2",
+ UpdateTxHash: "0x0cbff0ff3831d61345dbfda5b984e254c4bf87ecf80b45ccbb0635c0547a3b1a",
+ UpdateAt: 1279811,
+ UpdateTime: 1699781103,
+ }
+ buckets[i] = bucket
+ }
+ return buckets
+}
+
+func getTestVGFInfoBuckets(length int) []*types.VGFInfoBucket {
+ buckets := make([]*types.VGFInfoBucket, length)
+
+ for i := 0; i < length; i++ {
+ bucket := &types.VGFInfoBucket{
+ BucketInfo: &storage_types.BucketInfo{
+ Owner: testAccount,
+ BucketName: mockBucketName + strconv.Itoa(i),
+ Visibility: storage_types.VISIBILITY_TYPE_PUBLIC_READ,
+ Id: math.NewUintFromBigInt(big.NewInt(int64(i))),
+ SourceType: storage_types.SOURCE_TYPE_ORIGIN,
+ CreateAt: 1699781080,
+ PaymentAddress: testAccount,
+ GlobalVirtualGroupFamilyId: 3,
+ ChargedReadQuota: 0,
+ BucketStatus: storage_types.BUCKET_STATUS_CREATED,
+ },
+ Removed: false,
+ DeleteAt: 0,
+ DeleteReason: "",
+ Operator: testAccount,
+ CreateTxHash: "0x21c349a869bde1f44378936e2a9a15ed3fb2d54a43eaea8787960bba1134cdc2",
+ UpdateTxHash: "0x0cbff0ff3831d61345dbfda5b984e254c4bf87ecf80b45ccbb0635c0547a3b1a",
+ UpdateAt: 1279811,
+ UpdateTime: 1699781103,
+ Vgf: &virtual_types.GlobalVirtualGroupFamily{
+ Id: uint32(i),
+ PrimarySpId: uint32(3),
+ VirtualPaymentAddress: "0x26281179b8885F21f95b0a246c8AD70957A95A23",
+ },
+ }
+ buckets[i] = bucket
+ }
+ return buckets
+}
+
+func getTestStreamRecord() *payment_types.StreamRecord {
+ return &payment_types.StreamRecord{
+ Account: testAccount,
+ CrudTimestamp: 1699780994,
+ NetflowRate: math.NewIntFromBigInt(big.NewInt(int64(0))),
+ StaticBalance: math.NewIntFromBigInt(big.NewInt(int64(240000000000000001))),
+ BufferBalance: math.NewIntFromBigInt(big.NewInt(int64(0))),
+ LockBalance: math.NewIntFromBigInt(big.NewInt(int64(0))),
+ Status: payment_types.STREAM_ACCOUNT_STATUS_ACTIVE,
+ SettleTimestamp: 0,
+ OutFlowCount: 0,
+ FrozenNetflowRate: math.NewIntFromBigInt(big.NewInt(int64(0))),
+ }
+}
+
+func getTestPaymentAccountMeta() []*types.PaymentAccountMeta {
+ paymentAccounts := make([]*types.PaymentAccountMeta, 1)
+
+ paymentAccount := &types.PaymentAccountMeta{
+ StreamRecord: getTestStreamRecord(),
+ PaymentAccount: &types.PaymentAccount{
+ Address: testAccount,
+ Owner: testAccount,
+ Refundable: true,
+ UpdateAt: 1279659,
+ UpdateTime: 1699780707,
+ },
+ }
+ paymentAccounts[0] = paymentAccount
+ return paymentAccounts
+}
+
+func getTestObjectsInIdMap(length int) map[uint64]*types.Object {
+ objectsMap := make(map[uint64]*types.Object)
+ objects := getTestObjectsResponse(length)
+ for _, o := range objects {
+ objectsMap[o.ObjectInfo.Id.BigInt().Uint64()] = o
+ }
+ return objectsMap
+}
+
+func getOneTestObjectResponse() *types.Object {
+ owner := testAccount
+ object := &types.Object{
+ ObjectInfo: &storage_types.ObjectInfo{
+ Owner: owner,
+ Creator: owner,
+ BucketName: mockBucketName,
+ ObjectName: mockObjectName,
+ Id: math.NewUintFromString("24662"),
+ LocalVirtualGroupId: 1,
+ PayloadSize: 4802764,
+ Visibility: storage_types.VISIBILITY_TYPE_INHERIT,
+ ContentType: "application/octet-stream",
+ CreateAt: 1699781700,
+ ObjectStatus: storage_types.OBJECT_STATUS_SEALED,
+ Checksums: getSampleChecksum(),
+ },
+
+ LockedBalance: "0x0000000000000000000000000000000000000000000000000000000000000000",
+ UpdateAt: 1280048,
+ Operator: "0x03AbbEe8E426C9887A8ae3C34602AbCA42aeDFa0",
+ CreateTxHash: "0x491227c644bc89f5a058d92167c00d452c63a1dd8d5776c81617a41ec76fcc8c",
+ UpdateTxHash: "0x238737f109a40c675e1bef5ebfb2adef2cac0a723ee20fbd752e78efbf3d579e",
+ SealTxHash: "0x238737f109a40c675e1bef5ebfb2adef2cac0a723ee20fbd752e78efbf3d579e",
+ }
+ return object
+}
+
+func getTestObjectsResponse(objectLength int) []*types.Object {
+ length := objectLength
+ objects := make([]*types.Object, length)
+ owner := testAccount
+
+ for i := 0; i < length; i++ {
+ object := &types.Object{
+ ObjectInfo: &storage_types.ObjectInfo{
+ Owner: owner,
+ Creator: owner,
+ BucketName: mockBucketName,
+ ObjectName: mockObjectName + strconv.Itoa(i),
+ Id: math.NewUintFromBigInt(big.NewInt(int64(i))),
+ LocalVirtualGroupId: 1,
+ PayloadSize: 4802764,
+ Visibility: storage_types.VISIBILITY_TYPE_INHERIT,
+ ContentType: "application/octet-stream",
+ CreateAt: 1699781700,
+ ObjectStatus: storage_types.OBJECT_STATUS_SEALED,
+ Checksums: getSampleChecksum(),
+ },
+
+ LockedBalance: "0x0000000000000000000000000000000000000000000000000000000000000000",
+ UpdateAt: 1280048,
+ Operator: "0x03AbbEe8E426C9887A8ae3C34602AbCA42aeDFa0",
+ CreateTxHash: "0x491227c644bc89f5a058d92167c00d452c63a1dd8d5776c81617a41ec76fcc8c",
+ UpdateTxHash: "0x238737f109a40c675e1bef5ebfb2adef2cac0a723ee20fbd752e78efbf3d579e",
+ SealTxHash: "0x238737f109a40c675e1bef5ebfb2adef2cac0a723ee20fbd752e78efbf3d579e",
+ }
+ objects[i] = object
+ }
+ return objects
+}
+
+func getTestGroupsResponse(groupLength int) []*types.Group {
+ length := groupLength
+ groups := make([]*types.Group, length)
+ owner := testAccount
+
+ for i := 0; i < length; i++ {
+ group := &types.Group{
+ Group: &storage_types.GroupInfo{
+ Owner: owner,
+ GroupName: "TestGroupName " + strconv.Itoa(i),
+ SourceType: storage_types.SOURCE_TYPE_ORIGIN,
+ Id: math.NewUintFromBigInt(big.NewInt(int64(i))),
+ Extra: "",
+ },
+ NumberOfMembers: 1,
+ Removed: false,
+ UpdateAt: 1280048,
+ Operator: "0x03AbbEe8E426C9887A8ae3C34602AbCA42aeDFa0",
+ }
+ groups[i] = group
+ }
+ return groups
+}
+
+func getTestGroupMembersResponse(groupLength int) []*types.GroupMember {
+ length := groupLength
+ groupMembers := make([]*types.GroupMember, length)
+ for i := 0; i < length; i++ {
+ groupMember := &types.GroupMember{
+ Group: &storage_types.GroupInfo{
+ Owner: testAccount,
+ GroupName: "TestGroupName " + strconv.Itoa(i),
+ SourceType: storage_types.SOURCE_TYPE_ORIGIN,
+ Id: math.NewUintFromBigInt(big.NewInt(int64(i))),
+ Extra: "",
+ },
+ AccountId: testAccount,
+ Operator: testAccount,
+ CreateAt: 1376086,
+ CreateTime: 1700032197,
+ UpdateAt: 1376086,
+ UpdateTime: 1700032197,
+ Removed: false,
+ ExpirationTime: 253402300799,
+ }
+ groupMembers[i] = groupMember
+ }
+ return groupMembers
+}
+
+func TestGateModular_ListObjectsByBucketNameHandler(t *testing.T) {
+ mockData := getTestObjectsResponse(1000)
+ cases := []struct {
+ name string
+ fn func() *GateModular
+ request func() *http.Request
+ wantedResult string
+ wantedResultFn func(body string) bool
+ }{
+ {
+ name: "new request context error",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().ListObjectsByBucketName(gomock.Any(), gomock.Any(), gomock.Any(),
+ gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(),
+ ).Return(nil, uint64(0), uint64(0), false, "", "", "", "", nil, "", mockErr).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s.%s/", scheme, mockBucketName, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "mock error",
+ },
+ {
+ name: "wrong requestDelimiter",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s.%s/?max-keys=1000&delimiter=wrong_char&&continuation-token=NjM5LnBuZw==", scheme, mockBucketName, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "wrong BucketName",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s.%s/?max-keys=1000&delimiter=%%2F&&continuation-token=NjM5LnBuZw==", scheme, "aa", testDomain) // aa is an invalid bucket name
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "wrong requestMaxKeys",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s.%s/?max-keys=invalidMaxKey&delimiter=%%2F&&continuation-token=NjM5LnBuZw==", scheme, mockBucketName, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "wrong requestStartAfter",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s.%s/?max-keys=1000&delimiter=%%2F&&continuation-token=NjM5LnBuZw==&&start-after=%%2F%%2F", scheme, mockBucketName, testDomain) // %%2F%%2F means "//", which is an invalid start-after
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "wrong requestContinuationToken",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s.%s/?max-keys=1000&delimiter=%%2F&&continuation-token=NjM5LnBuZw==d", scheme, mockBucketName, testDomain) // NjM5LnBuZw==d is an invalid requestContinuationToken
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "wrong requestContinuationToken2",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ invalidContinuationToken := base64.StdEncoding.EncodeToString([]byte("//"))
+ path := fmt.Sprintf("%s%s.%s/?max-keys=1000&delimiter=%%2F&&continuation-token=%s", scheme, mockBucketName, testDomain, invalidContinuationToken)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "wrong requestContinuationToken3",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ invalidContinuationToken := base64.StdEncoding.EncodeToString([]byte("not_start_with_prefix"))
+ path := fmt.Sprintf("%s%s.%s/?max-keys=1000&delimiter=%%2F&&continuation-token=%s&&prefix=%s", scheme, mockBucketName, testDomain, invalidContinuationToken, "a_sample_prefix")
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "wrong requestIncludeRemoved",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s.%s/?max-keys=1000&delimiter=%%2F&&include-removed=invalid", scheme, mockBucketName, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "wrong prefix",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ invalidPrefix := "%2F%2F" // this is an invalid prefix
+ path := fmt.Sprintf("%s%s.%s/?max-keys=1000&delimiter=%%2F&&prefix=%s", scheme, mockBucketName, testDomain, invalidPrefix)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ // Disable the following json response unit test and will add it back once we add json response support in metadata_handler soon.
+ //{
+ // name: "json response",
+ // fn: func() *GateModular {
+ // g := setup(t)
+ // ctrl := gomock.NewController(t)
+ // clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ // clientMock.EXPECT().ListObjectsByBucketName(gomock.Any(), gomock.Any(), gomock.Any(),
+ // gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(),
+ // ).Return(mockData, uint64(0), uint64(0), false, "", "", "", "", nil, "", nil).Times(1)
+ // g.baseApp.SetGfSpClient(clientMock)
+ // return g
+ // },
+ // request: func() *http.Request {
+ // path := fmt.Sprintf("%s%s.%s/?max-keys=1000&delimiter=%%2F&format=json", scheme, mockBucketName, testDomain)
+ // req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ // return req
+ // },
+ // wantedResultFn: func(body string) bool {
+ // var res types.GfSpListObjectsByBucketNameResponse
+ // err := json.Unmarshal([]byte(body), &res)
+ // if err != nil {
+ // return false
+ // }
+ // assert.Equal(t, len(mockData), len(res.Objects))
+ // assert.Equal(t, mockData[0].ObjectInfo.Id, res.Objects[0].ObjectInfo.Id)
+ // return true
+ // },
+ //},
+ {
+ name: "xml response",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().ListObjectsByBucketName(gomock.Any(), gomock.Any(), gomock.Any(),
+ gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(),
+ ).Return(mockData, uint64(0), uint64(0), false, "", "", "", "", nil, "", nil).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s.%s/?max-keys=1000&delimiter=%%2F", scheme, mockBucketName, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResultFn: func(body string) bool {
+ var res types.GfSpListObjectsByBucketNameResponse
+ err := xml.Unmarshal([]byte(body), &res)
+ if err != nil {
+ return false
+ }
+ assert.Equal(t, len(mockData), len(res.Objects))
+ assert.Equal(t, mockData[0].ObjectInfo.Id, res.Objects[0].ObjectInfo.Id)
+ return true
+ },
+ },
+ }
+ for _, tt := range cases {
+ t.Run(tt.name, func(t *testing.T) {
+ router := mockListObjectsByBucketNameRoute(t, tt.fn())
+ w := httptest.NewRecorder()
+ begin := time.Now()
+ router.ServeHTTP(w, tt.request())
+ end := time.Now()
+ assert.Less(t, end.UnixMilli()-begin.UnixMilli(), int64(1000)) // we expected this API can return response in 1 sec after it gets data from DB.
+ if tt.wantedResult != "" {
+ assert.Contains(t, w.Body.String(), tt.wantedResult)
+ }
+ if tt.wantedResultFn != nil {
+ assert.True(t, tt.wantedResultFn(w.Body.String()))
+ }
+ })
+ }
+}
+
+func mockGetObjectMetaRoute(t *testing.T, g *GateModular) *mux.Router {
+ t.Helper()
+ router := mux.NewRouter().SkipClean(true)
+ var routers []*mux.Router
+ routers = append(routers, router.Host("{bucket:.+}."+g.domain).Subrouter())
+ routers = append(routers, router.PathPrefix("/{bucket}").Subrouter())
+ for _, r := range routers {
+ r.NewRoute().Name(getObjectMetaRouterName).Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc(g.getObjectMetaHandler).
+ Queries(GetObjectMetaQuery, "")
+ }
+ return router
+}
+
+func TestGateModular_GetObjectMetaHandler(t *testing.T) {
+ cases := []struct {
+ name string
+ fn func() *GateModular
+ request func() *http.Request
+ wantedResult string
+ wantedResultFn func(body string) bool
+ }{
+ {
+ name: "new request context error",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetObjectMeta(gomock.Any(), gomock.Any(), gomock.Any(),
+ gomock.Any()).Return(nil, mockErr).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s.%s/%s?%s", scheme, mockBucketName, testDomain, mockObjectName, GetObjectMetaQuery)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "mock error",
+ },
+ {
+ name: "invalid bucket name",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetObjectMeta(gomock.Any(), gomock.Any(), gomock.Any(),
+ gomock.Any()).Return(nil, mockErr).Times(0)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s.%s/%s?%s", scheme, invalidBucketName, testDomain, mockObjectName, GetObjectMetaQuery)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "invalid object name",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetObjectMeta(gomock.Any(), gomock.Any(), gomock.Any(),
+ gomock.Any()).Return(nil, mockErr).Times(0)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s.%s/%s?%s", scheme, mockBucketName, testDomain, invalidObjectName, GetObjectMetaQuery)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "xml response",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetObjectMeta(gomock.Any(), gomock.Any(), gomock.Any(),
+ gomock.Any()).Return(getOneTestObjectResponse(), nil).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s.%s/%s?%s", scheme, mockBucketName, testDomain, mockObjectName, GetObjectMetaQuery)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResultFn: func(body string) bool {
+ assert.Equal(t, "",
+ body)
+ return true
+ },
+ },
+ }
+ for _, tt := range cases {
+ t.Run(tt.name, func(t *testing.T) {
+ router := mockGetObjectMetaRoute(t, tt.fn())
+ w := httptest.NewRecorder()
+ router.ServeHTTP(w, tt.request())
+ if tt.wantedResult != "" {
+ assert.Contains(t, w.Body.String(), tt.wantedResult)
+ }
+ if tt.wantedResultFn != nil {
+ assert.True(t, tt.wantedResultFn(w.Body.String()))
+ }
+ })
+ }
+}
+
+func mockListObjectsByIDsHandlerRoute(t *testing.T, g *GateModular) *mux.Router {
+ t.Helper()
+ router := mux.NewRouter().SkipClean(true)
+ router.Path("/").Name(listObjectsByIDsRouterName).Methods(http.MethodGet).Queries(ListObjectsByIDsQuery, "").HandlerFunc(g.listObjectsByIDsHandler)
+ return router
+}
+
+func TestGateModular_ListObjectsByIDsHandler(t *testing.T) {
+
+ cases := []struct {
+ name string
+ fn func() *GateModular
+ request func() *http.Request
+ wantedResult string
+ wantedResultFn func(body string) bool
+ }{
+ {
+ name: "new request context error",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().ListObjectsByIDs(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, mockErr).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?%s&ids=%s", scheme, testDomain, ListObjectsByIDsQuery, "1,2,3,4")
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "mock error",
+ },
+ {
+ name: "invalid id",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?%s&ids=%s", scheme, testDomain, ListObjectsByIDsQuery, "a,2,3,4")
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "invalid id number",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ ids := "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100"
+ path := fmt.Sprintf("%s%s/?%s&ids=%s", scheme, testDomain, ListObjectsByIDsQuery, ids)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "repeated id number",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ ids := "1,1"
+ path := fmt.Sprintf("%s%s/?%s&ids=%s", scheme, testDomain, ListObjectsByIDsQuery, ids)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "xml response",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().ListObjectsByIDs(gomock.Any(), gomock.Any(), gomock.Any()).Return(getTestObjectsInIdMap(1), nil).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ ids := "1"
+ path := fmt.Sprintf("%s%s/?%s&ids=%s", scheme, testDomain, ListObjectsByIDsQuery, ids)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResultFn: func(body string) bool {
+ assert.Equal(t, "00xF72aDa8130f934887755492879496b026665FbAB0xF72aDa8130f934887755492879496b026665FbABmock-bucket-namemock-object-name00148027643application/octet-stream1699781700100tPsLBcgLxRVKTRJCeYw5FVj0jjqPsqFnbDCr77pf7RA=7YqCbwK/qC+zaAoJvd971fuJCE0OVQ9ky8bgomUkmRI=i59qS3vgvN8QIcNKOJggtN4JsZRLYt1ugeGDtP6x7Sk=tBBu4BPpANbc12SO5TVeQ64DtKwl0F2inE29H9jAw54=vOw+loeUIXXPEvfYNFmnElTIxj/b0dEEBBF1YbKOoEI=e0nSN4a5u3EDPaAqemGDZ5gYJ0l6NUjtalmj/BH2uWE=rRm6iKPMc8gZbw1WKKF2kPXveU2VFEh2izs9e8ovfwk=0x0000000000000000000000000000000000000000000000000000000000000000false128004800x03AbbEe8E426C9887A8ae3C34602AbCA42aeDFa00x491227c644bc89f5a058d92167c00d452c63a1dd8d5776c81617a41ec76fcc8c0x238737f109a40c675e1bef5ebfb2adef2cac0a723ee20fbd752e78efbf3d579e0x238737f109a40c675e1bef5ebfb2adef2cac0a723ee20fbd752e78efbf3d579e",
+ body)
+ return true
+ },
+ },
+ }
+ for _, tt := range cases {
+ t.Run(tt.name, func(t *testing.T) {
+ router := mockListObjectsByIDsHandlerRoute(t, tt.fn())
+ w := httptest.NewRecorder()
+ router.ServeHTTP(w, tt.request())
+ if tt.wantedResult != "" {
+ assert.Contains(t, w.Body.String(), tt.wantedResult)
+ }
+ if tt.wantedResultFn != nil {
+ assert.True(t, tt.wantedResultFn(w.Body.String()))
+ }
+ })
+ }
+}
+
+func mockListGroupsByIDsHandlerRoute(t *testing.T, g *GateModular) *mux.Router {
+ t.Helper()
+ router := mux.NewRouter().SkipClean(true)
+ router.Path("/").Name(listGroupsByIDsRouterName).Methods(http.MethodGet).Queries(ListGroupsByIDsQuery, "").HandlerFunc(g.listGroupsByIDsHandler)
+ return router
+}
+
+func TestGateModular_ListGroupsByIDsHandler(t *testing.T) {
+
+ cases := []struct {
+ name string
+ fn func() *GateModular
+ request func() *http.Request
+ wantedResult string
+ wantedResultFn func(body string) bool
+ }{
+ {
+ name: "new request context error",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().ListGroupsByIDs(gomock.Any(), gomock.Any()).Return(nil, mockErr).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?%s&ids=%s", scheme, testDomain, ListGroupsByIDsQuery, "1,2,3,4")
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "mock error",
+ },
+ {
+ name: "invalid id",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?%s&ids=%s", scheme, testDomain, ListGroupsByIDsQuery, "a,2,3,4")
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "invalid id number",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ ids := "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100"
+ path := fmt.Sprintf("%s%s/?%s&ids=%s", scheme, testDomain, ListGroupsByIDsQuery, ids)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "repeated id number",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ ids := "1,1"
+ path := fmt.Sprintf("%s%s/?%s&ids=%s", scheme, testDomain, ListGroupsByIDsQuery, ids)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "xml response",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().ListGroupsByIDs(gomock.Any(), gomock.Any()).Return(getTestGroupsInIdMap(1), nil).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ ids := "1"
+ path := fmt.Sprintf("%s%s/?%s&ids=%s", scheme, testDomain, ListGroupsByIDsQuery, ids)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResultFn: func(body string) bool {
+ assert.Equal(t, "00xF72aDa8130f934887755492879496b026665FbABTestGroupName 0000x03AbbEe8E426C9887A8ae3C34602AbCA42aeDFa000128004801false",
+ body)
+ return true
+ },
+ },
+ }
+ for _, tt := range cases {
+ t.Run(tt.name, func(t *testing.T) {
+ router := mockListGroupsByIDsHandlerRoute(t, tt.fn())
+ w := httptest.NewRecorder()
+ router.ServeHTTP(w, tt.request())
+ if tt.wantedResult != "" {
+ assert.Contains(t, w.Body.String(), tt.wantedResult)
+ }
+ if tt.wantedResultFn != nil {
+ assert.True(t, tt.wantedResultFn(w.Body.String()))
+ }
+ })
+ }
+}
+
+func mockGetGroupListHandlerRoute(t *testing.T, g *GateModular) *mux.Router {
+ t.Helper()
+ router := mux.NewRouter().SkipClean(true)
+ router.Path("/").Name(getGroupListRouterName).Methods(http.MethodGet).Queries(GetGroupListGroupQuery, "").HandlerFunc(g.getGroupListHandler)
+ return router
+}
+
+func TestGateModular_GetGroupListHandler(t *testing.T) {
+
+ cases := []struct {
+ name string
+ fn func() *GateModular
+ request func() *http.Request
+ wantedResult string
+ wantedResultFn func(body string) bool
+ }{
+ {
+ name: "new request context error",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetGroupList(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, int64(0), mockErr).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?group-query&source-type=SOURCE_TYPE_ORIGIN&limit=10&offset=0&name=e&prefix=t", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "mock error",
+ },
+ {
+ name: "blank name",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?group-query&source-type=SOURCE_TYPE_ORIGIN&limit=10&offset=0&name=&prefix=t", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "blank prefix",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?group-query&source-type=SOURCE_TYPE_ORIGIN&limit=10&offset=0&name=n&prefix=", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "bad offset",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?group-query&source-type=SOURCE_TYPE_ORIGIN&limit=&offset=a&name=n&prefix=t", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "bad limit",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?group-query&source-type=SOURCE_TYPE_ORIGIN&limit=a&offset=&name=n&prefix=t", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "limit is negative",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?group-query&source-type=SOURCE_TYPE_ORIGIN&limit=-1&offset=&name=n&prefix=t", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "bad sourceType",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?group-query&source-type=SOURCE_TYPE_UNKNOWN&limit=1&offset=0&name=n&prefix=t", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "xml response",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetGroupList(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(getTestGroupsResponse(1), int64(1), nil).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?group-query&source-type=SOURCE_TYPE_ORIGIN&limit=1&offset=0&name=n&prefix=t", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResultFn: func(body string) bool {
+ assert.Equal(t, "0xF72aDa8130f934887755492879496b026665FbABTestGroupName 0000x03AbbEe8E426C9887A8ae3C34602AbCA42aeDFa000128004801false1",
+ body)
+ return true
+ },
+ },
+
+ {
+ name: "xml response for large limit", // return 1000 records when limit is more than 1000
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetGroupList(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Eq(int64(1000)), gomock.Any(), gomock.Any()).Return(getTestGroupsResponse(1000), int64(1), nil).AnyTimes()
+ clientMock.EXPECT().GetGroupList(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Eq(int64(1001)), gomock.Any(), gomock.Any()).Return(getTestGroupsResponse(1001), int64(1), nil).AnyTimes()
+ clientMock.EXPECT().GetGroupList(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Eq(int64(50)), gomock.Any(), gomock.Any()).Return(getTestGroupsResponse(50), int64(1), nil).AnyTimes()
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?group-query&source-type=SOURCE_TYPE_ORIGIN&limit=1001&offset=0&name=n&prefix=t", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResultFn: func(body string) bool {
+ var res types.GfSpGetGroupListResponse
+ err := xml.Unmarshal([]byte(body), &res)
+ if err != nil {
+ return false
+ }
+ assert.Equal(t, 1000, len(res.Groups))
+ return true
+ },
+ },
+ {
+ name: "xml response for default limit", // return 50 records when limit is not set
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetGroupList(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Eq(int64(1000)), gomock.Any(), gomock.Any()).Return(getTestGroupsResponse(1000), int64(1), nil).AnyTimes()
+ clientMock.EXPECT().GetGroupList(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Eq(int64(1001)), gomock.Any(), gomock.Any()).Return(getTestGroupsResponse(1001), int64(1), nil).AnyTimes()
+ clientMock.EXPECT().GetGroupList(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Eq(int64(50)), gomock.Any(), gomock.Any()).Return(getTestGroupsResponse(50), int64(1), nil).AnyTimes()
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?group-query&source-type=SOURCE_TYPE_ORIGIN&offset=0&name=n&prefix=t", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResultFn: func(body string) bool {
+ var res types.GfSpGetGroupListResponse
+ err := xml.Unmarshal([]byte(body), &res)
+ if err != nil {
+ return false
+ }
+ assert.Equal(t, 50, len(res.Groups))
+ return true
+ },
+ },
+ }
+ for _, tt := range cases {
+ t.Run(tt.name, func(t *testing.T) {
+ router := mockGetGroupListHandlerRoute(t, tt.fn())
+ w := httptest.NewRecorder()
+ router.ServeHTTP(w, tt.request())
+ if tt.wantedResult != "" {
+ assert.Contains(t, w.Body.String(), tt.wantedResult)
+ }
+ if tt.wantedResultFn != nil {
+ assert.True(t, tt.wantedResultFn(w.Body.String()))
+ }
+ })
+ }
+}
+
+func mockListPaymentAccountStreamsHandlerRoute(t *testing.T, g *GateModular) *mux.Router {
+ t.Helper()
+ router := mux.NewRouter().SkipClean(true)
+ router.Path("/").Name(listPaymentAccountStreamsRouterName).Methods(http.MethodGet).Queries(ListPaymentAccountStreamsQuery, "").HandlerFunc(g.listPaymentAccountStreamsHandler)
+ return router
+}
+
+func TestGateModular_ListPaymentAccountStreamsHandler(t *testing.T) {
+
+ cases := []struct {
+ name string
+ fn func() *GateModular
+ request func() *http.Request
+ wantedResult string
+ wantedResultFn func(body string) bool
+ }{
+ {
+ name: "new request context error",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().ListPaymentAccountStreams(gomock.Any(), gomock.Any()).Return(nil, mockErr).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?%s&%s=%s", scheme, testDomain, ListPaymentAccountStreamsQuery, PaymentAccountQuery, testAccount)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "mock error",
+ },
+ {
+ name: "invalid payment account",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?%s&%s=%s", scheme, testDomain, ListPaymentAccountStreamsQuery, PaymentAccountQuery, "invalid_payment_account")
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "xml response",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().ListPaymentAccountStreams(gomock.Any(), gomock.Any()).Return(getTestBuckets(1), nil).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?%s&%s=%s", scheme, testDomain, ListPaymentAccountStreamsQuery, PaymentAccountQuery, testAccount)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResultFn: func(body string) bool {
+ assert.Equal(t, "0xF72aDa8130f934887755492879496b026665FbABmock-bucket-name010016997810800xF72aDa8130f934887755492879496b026665FbAB300false00xF72aDa8130f934887755492879496b026665FbAB0x21c349a869bde1f44378936e2a9a15ed3fb2d54a43eaea8787960bba1134cdc20x0cbff0ff3831d61345dbfda5b984e254c4bf87ecf80b45ccbb0635c0547a3b1a12798111699781103",
+ body)
+ return true
+ },
+ },
+ }
+ for _, tt := range cases {
+ t.Run(tt.name, func(t *testing.T) {
+ router := mockListPaymentAccountStreamsHandlerRoute(t, tt.fn())
+ w := httptest.NewRecorder()
+ router.ServeHTTP(w, tt.request())
+ if tt.wantedResult != "" {
+ assert.Contains(t, w.Body.String(), tt.wantedResult)
+ }
+ if tt.wantedResultFn != nil {
+ assert.True(t, tt.wantedResultFn(w.Body.String()))
+ }
+ })
+ }
+}
+
+func mockListUserPaymentAccountsHandlerRoute(t *testing.T, g *GateModular) *mux.Router {
+ t.Helper()
+ router := mux.NewRouter().SkipClean(true)
+ router.Path("/").Name(listUserPaymentAccountsRouterName).Methods(http.MethodGet).Queries(ListUserPaymentAccountsQuery, "").HandlerFunc(g.listUserPaymentAccountsHandler)
+ return router
+}
+
+func TestGateModular_ListUserPaymentAccountsHandler(t *testing.T) {
+
+ cases := []struct {
+ name string
+ fn func() *GateModular
+ request func() *http.Request
+ wantedResult string
+ wantedResultFn func(body string) bool
+ }{
+ {
+ name: "new request context error",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().ListUserPaymentAccounts(gomock.Any(), gomock.Any()).Return(nil, mockErr).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?%s", scheme, testDomain, ListUserPaymentAccountsQuery)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, testAccount)
+
+ return req
+ },
+ wantedResult: "mock error",
+ },
+ {
+ name: "invalid payment account",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?%s", scheme, testDomain, ListUserPaymentAccountsQuery)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, "invalid_payment_account")
+
+ return req
+ },
+ wantedResult: "invalid request header",
+ },
+ {
+ name: "xml response",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().ListUserPaymentAccounts(gomock.Any(), gomock.Any()).Return(getTestPaymentAccountMeta(), nil).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?%s", scheme, testDomain, ListUserPaymentAccountsQuery)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, testAccount)
+
+ return req
+ },
+ wantedResultFn: func(body string) bool {
+ assert.Equal(t, "0xF72aDa8130f934887755492879496b026665FbAB0xF72aDa8130f934887755492879496b026665FbABtrue127965916997807070xF72aDa8130f934887755492879496b026665FbAB16997809940240000000000000001000000",
+ body)
+ return true
+ },
+ },
+ }
+ for _, tt := range cases {
+ t.Run(tt.name, func(t *testing.T) {
+ router := mockListUserPaymentAccountsHandlerRoute(t, tt.fn())
+ w := httptest.NewRecorder()
+ router.ServeHTTP(w, tt.request())
+ if tt.wantedResult != "" {
+ assert.Contains(t, w.Body.String(), tt.wantedResult)
+ }
+ if tt.wantedResultFn != nil {
+ assert.True(t, tt.wantedResultFn(w.Body.String()))
+ }
+ })
+ }
+}
+
+func mockListBucketsByIDsHandlerRoute(t *testing.T, g *GateModular) *mux.Router {
+ t.Helper()
+ router := mux.NewRouter().SkipClean(true)
+ router.Path("/").Name(listBucketsByIDsRouterName).Methods(http.MethodGet).Queries(ListBucketsByIDsQuery, "").HandlerFunc(g.listBucketsByIDsHandler)
+ return router
+}
+
+func TestGateModular_ListBucketsByIDsHandler(t *testing.T) {
+
+ cases := []struct {
+ name string
+ fn func() *GateModular
+ request func() *http.Request
+ wantedResult string
+ wantedResultFn func(body string) bool
+ }{
+ {
+ name: "new request context error",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().ListBucketsByIDs(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, mockErr).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?%s&ids=%s", scheme, testDomain, ListBucketsByIDsQuery, "1,2,3,4")
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "mock error",
+ },
+ {
+ name: "invalid id",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?%s&ids=%s", scheme, testDomain, ListBucketsByIDsQuery, "a,2,3,4")
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "invalid id number",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ ids := "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100"
+ path := fmt.Sprintf("%s%s/?%s&ids=%s", scheme, testDomain, ListBucketsByIDsQuery, ids)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "repeated id number",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ ids := "1,1"
+ path := fmt.Sprintf("%s%s/?%s&ids=%s", scheme, testDomain, ListBucketsByIDsQuery, ids)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "xml response",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().ListBucketsByIDs(gomock.Any(), gomock.Any(), gomock.Any()).Return(getTestBucketsInIdMap(1), nil).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ ids := "1"
+ path := fmt.Sprintf("%s%s/?%s&ids=%s", scheme, testDomain, ListBucketsByIDsQuery, ids)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResultFn: func(body string) bool {
+ assert.Equal(t, "00xF72aDa8130f934887755492879496b026665FbABmock-bucket-name010016997810800xF72aDa8130f934887755492879496b026665FbAB300false00xF72aDa8130f934887755492879496b026665FbAB0x21c349a869bde1f44378936e2a9a15ed3fb2d54a43eaea8787960bba1134cdc20x0cbff0ff3831d61345dbfda5b984e254c4bf87ecf80b45ccbb0635c0547a3b1a12798111699781103",
+ body)
+ return true
+ },
+ },
+ }
+ for _, tt := range cases {
+ t.Run(tt.name, func(t *testing.T) {
+ router := mockListBucketsByIDsHandlerRoute(t, tt.fn())
+ w := httptest.NewRecorder()
+ router.ServeHTTP(w, tt.request())
+ if tt.wantedResult != "" {
+ assert.Contains(t, w.Body.String(), tt.wantedResult)
+ }
+ if tt.wantedResultFn != nil {
+ assert.True(t, tt.wantedResultFn(w.Body.String()))
+ }
+ })
+ }
+}
+
+func mockGetUserGroupsHandlerRoute(t *testing.T, g *GateModular) *mux.Router {
+ t.Helper()
+ router := mux.NewRouter().SkipClean(true)
+ router.Path("/").Name(getUserGroupsRouterName).Methods(http.MethodGet).Queries(GetUserGroupsQuery, "").HandlerFunc(g.getUserGroupsHandler)
+ return router
+}
+
+func TestGateModular_GetUserGroupsHandler(t *testing.T) {
+
+ cases := []struct {
+ name string
+ fn func() *GateModular
+ request func() *http.Request
+ wantedResult string
+ wantedResultFn func(body string) bool
+ }{
+ {
+ name: "new request context error",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetUserGroups(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, mockErr).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?user-groups&start-after=0&limit=1000", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, testAccount)
+ return req
+ },
+ wantedResult: "mock error",
+ },
+ {
+ name: "invalid user address",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?user-groups&start-after=0&limit=1000", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, "invalid_account")
+ return req
+ },
+ wantedResult: "invalid request header",
+ },
+ {
+ name: "invalid requestStartAfter",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?user-groups&start-after=a&limit=1000", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, testAccount)
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "invalid limit",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?user-groups&limit=a", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, testAccount)
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "xmlResponse",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetUserGroups(gomock.Any(), gomock.Eq(testAccount), gomock.Eq(uint64(2)), gomock.Eq(uint32(1))).Return(getTestGroupMembersResponse(1), nil).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?user-groups&start-after=2&limit=1", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, testAccount)
+ return req
+ },
+ wantedResult: "0xF72aDa8130f934887755492879496b026665FbABTestGroupName 0000xF72aDa8130f934887755492879496b026665FbAB0xF72aDa8130f934887755492879496b026665FbAB1376086170003219713760861700032197false253402300799",
+ wantedResultFn: func(body string) bool {
+ var res types.GfSpGetUserGroupsResponse
+ err := xml.Unmarshal([]byte(body), &res)
+ if err != nil {
+ return false
+ }
+ assert.Equal(t, 1, len(res.Groups))
+ return true
+ },
+ },
+ {
+ name: "large xmlResponse",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetUserGroups(gomock.Any(), gomock.Eq(testAccount), gomock.Eq(uint64(2)), gomock.Eq(uint32(1000))).Return(getTestGroupMembersResponse(1000), nil).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?user-groups&start-after=2&limit=1000", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, testAccount)
+ return req
+ },
+ wantedResultFn: func(body string) bool {
+ var res types.GfSpGetUserGroupsResponse
+ err := xml.Unmarshal([]byte(body), &res)
+ if err != nil {
+ return false
+ }
+ assert.Equal(t, 1000, len(res.Groups))
+ return true
+ },
+ },
+ }
+ for _, tt := range cases {
+ t.Run(tt.name, func(t *testing.T) {
+ router := mockGetUserGroupsHandlerRoute(t, tt.fn())
+ w := httptest.NewRecorder()
+ begin := time.Now()
+ router.ServeHTTP(w, tt.request())
+ end := time.Now()
+ log.Printf("GetUserGroupsHandler takes %d to finish", end.UnixMilli()-begin.UnixMilli())
+
+ assert.Less(t, end.UnixMilli()-begin.UnixMilli(), int64(300)) // we expected this API can return response in 0.3 sec after it gets data from DB.
+ if tt.wantedResult != "" {
+ assert.Contains(t, w.Body.String(), tt.wantedResult)
+ }
+ if tt.wantedResultFn != nil {
+ assert.True(t, tt.wantedResultFn(w.Body.String()))
+ }
+ })
+ }
+}
+
+func mockGetGroupMembersHandlerRoute(t *testing.T, g *GateModular) *mux.Router {
+ t.Helper()
+ router := mux.NewRouter().SkipClean(true)
+ router.Path("/").Name(getGroupMembersRouterName).Methods(http.MethodGet).Queries(GetGroupMembersQuery, "").HandlerFunc(g.getGroupMembersHandler)
+ return router
+}
+
+func TestGateModular_GetGroupMembersHandler(t *testing.T) {
+
+ cases := []struct {
+ name string
+ fn func() *GateModular
+ request func() *http.Request
+ wantedResult string
+ wantedResultFn func(body string) bool
+ }{
+ {
+ name: "new request context error",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetGroupMembers(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, mockErr).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?group-members&group-id=2&limit=10", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "mock error",
+ },
+ {
+ name: "invalid requestStartAfter",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?group-members&group-id=2&limit=10&start-after=a", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "invalid group id",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?group-members&group-id=a&limit=10", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "invalid limit",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?group-members&group-id=2&limit=a", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "xmlResponse",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetGroupMembers(gomock.Any(), gomock.Eq(uint64(73)), gomock.Eq("0x76d32704A1f415a0a8139997Bb40978b9EEf031f"), gomock.Eq(uint32(1))).Return(getTestGroupMembersResponse(1), nil).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?group-members&group-id=73&limit=1&start-after=0x76d32704A1f415a0a8139997Bb40978b9EEf031f", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "0xF72aDa8130f934887755492879496b026665FbABTestGroupName 0000xF72aDa8130f934887755492879496b026665FbAB0xF72aDa8130f934887755492879496b026665FbAB1376086170003219713760861700032197false253402300799",
+ wantedResultFn: func(body string) bool {
+ var res types.GfSpGetGroupMembersResponse
+ err := xml.Unmarshal([]byte(body), &res)
+ if err != nil {
+ return false
+ }
+ assert.Equal(t, 1, len(res.Groups))
+ return true
+ },
+ },
+ {
+ name: "large xmlResponse",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetGroupMembers(gomock.Any(), gomock.Eq(uint64(73)), gomock.Eq("0x76d32704A1f415a0a8139997Bb40978b9EEf031f"), gomock.Eq(uint32(1000))).Return(getTestGroupMembersResponse(1000), nil).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?group-members&group-id=73&limit=1000&start-after=0x76d32704A1f415a0a8139997Bb40978b9EEf031f", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResultFn: func(body string) bool {
+ var res types.GfSpGetGroupMembersResponse
+ err := xml.Unmarshal([]byte(body), &res)
+ if err != nil {
+ return false
+ }
+ assert.Equal(t, 1000, len(res.Groups))
+ return true
+ },
+ },
+ }
+ for _, tt := range cases {
+ t.Run(tt.name, func(t *testing.T) {
+ router := mockGetGroupMembersHandlerRoute(t, tt.fn())
+ w := httptest.NewRecorder()
+ begin := time.Now()
+ router.ServeHTTP(w, tt.request())
+ end := time.Now()
+ log.Printf("GetGroupMembersHandler takes %d to finish", end.UnixMilli()-begin.UnixMilli())
+ assert.Less(t, end.UnixMilli()-begin.UnixMilli(), int64(300)) // we expected this API can return response in 0.3 sec after it gets data from DB.
+ if tt.wantedResult != "" {
+ assert.Contains(t, w.Body.String(), tt.wantedResult)
+ }
+ if tt.wantedResultFn != nil {
+ assert.True(t, tt.wantedResultFn(w.Body.String()))
+ }
+ })
+ }
+}
+
+func mockGetUserOwnedGroupsHandlerRoute(t *testing.T, g *GateModular) *mux.Router {
+ t.Helper()
+ router := mux.NewRouter().SkipClean(true)
+ router.Path("/").Name(getUserOwnedGroupsRouterName).Methods(http.MethodGet).Queries(GetUserOwnedGroupsQuery, "").HandlerFunc(g.getUserOwnedGroupsHandler)
+ return router
+}
+
+func TestGateModular_GetUserOwnedGroupsHandler(t *testing.T) {
+
+ cases := []struct {
+ name string
+ fn func() *GateModular
+ request func() *http.Request
+ wantedResult string
+ wantedResultFn func(body string) bool
+ }{
+ {
+ name: "new request context error",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetUserOwnedGroups(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, mockErr).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?owned-groups&start-after=15&limit=1", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, testAccount)
+ return req
+ },
+ wantedResult: "mock error",
+ },
+ {
+ name: "invalid user address",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?owned-groups&start-after=15&limit=1", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, "invalid_account")
+ return req
+ },
+ wantedResult: "invalid request header",
+ },
+
+ {
+ name: "invalid requestStartAfter",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?owned-groups&start-after=a&limit=1", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, testAccount)
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "invalid limit",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?owned-groups&start-after=15&limit=a", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, testAccount)
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "xmlResponse",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetUserOwnedGroups(gomock.Any(), gomock.Eq(testAccount), gomock.Eq(uint64(15)), gomock.Eq(uint32(1))).Return(getTestGroupMembersResponse(1), nil).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?owned-groups&start-after=15&limit=1", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, testAccount)
+ return req
+ },
+ wantedResult: "0xF72aDa8130f934887755492879496b026665FbABTestGroupName 0000xF72aDa8130f934887755492879496b026665FbAB0xF72aDa8130f934887755492879496b026665FbAB1376086170003219713760861700032197false253402300799",
+ wantedResultFn: func(body string) bool {
+ var res types.GfSpGetUserOwnedGroupsResponse
+ err := xml.Unmarshal([]byte(body), &res)
+ if err != nil {
+ return false
+ }
+ assert.Equal(t, 1, len(res.Groups))
+ return true
+ },
+ },
+ {
+ name: "large xmlResponse",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetUserOwnedGroups(gomock.Any(), gomock.Eq(testAccount), gomock.Eq(uint64(15)), gomock.Eq(uint32(1000))).Return(getTestGroupMembersResponse(1000), nil).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?owned-groups&start-after=15&limit=1000", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, testAccount)
+ return req
+ },
+ wantedResultFn: func(body string) bool {
+ var res types.GfSpGetUserOwnedGroupsResponse
+ err := xml.Unmarshal([]byte(body), &res)
+ if err != nil {
+ return false
+ }
+ assert.Equal(t, 1000, len(res.Groups))
+ return true
+ },
+ },
+ }
+ for _, tt := range cases {
+ t.Run(tt.name, func(t *testing.T) {
+ router := mockGetUserOwnedGroupsHandlerRoute(t, tt.fn())
+ w := httptest.NewRecorder()
+ begin := time.Now()
+ router.ServeHTTP(w, tt.request())
+ end := time.Now()
+ log.Printf("GetUserOwnedGroupsHandler takes %d to finish", end.UnixMilli()-begin.UnixMilli())
+ assert.Less(t, end.UnixMilli()-begin.UnixMilli(), int64(300)) // we expected this API can return response in 0.3 sec after it gets data from DB.
+ if tt.wantedResult != "" {
+ assert.Contains(t, w.Body.String(), tt.wantedResult)
+ }
+ if tt.wantedResultFn != nil {
+ assert.True(t, tt.wantedResultFn(w.Body.String()))
+ }
+ })
+ }
+}
+
+func mockGetBucketMetaHandlerRoute(t *testing.T, g *GateModular) *mux.Router {
+ t.Helper()
+ router := mux.NewRouter().SkipClean(true)
+ var routers []*mux.Router
+ routers = append(routers, router.Host("{bucket:.+}."+g.domain).Subrouter())
+ routers = append(routers, router.PathPrefix("/{bucket}").Subrouter())
+ for _, r := range routers {
+ r.NewRoute().Name(getBucketMetaRouterName).Methods(http.MethodGet).Queries(GetBucketMetaQuery, "").HandlerFunc(g.getBucketMetaHandler)
+ }
+ return router
+}
+
+func TestGateModular_GetBucketMetaHandler(t *testing.T) {
+
+ cases := []struct {
+ name string
+ fn func() *GateModular
+ request func() *http.Request
+ wantedResult string
+ wantedResultFn func(body string) bool
+ }{
+ {
+ name: "new request context error",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetBucketMeta(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil, mockErr).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/%s?%s", scheme, testDomain, mockBucketName, GetBucketMetaQuery)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "mock error",
+ },
+ {
+ name: "wrong BucketName",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/%s?%s", scheme, testDomain, "aa", GetBucketMetaQuery) // aa is an invalid bucket name
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+ {
+ name: "xml response",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetBucketMeta(gomock.Any(), gomock.Any(), gomock.Any()).Return(getTestVGFInfoBuckets(1)[0], getTestStreamRecord(), nil).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/%s?%s", scheme, testDomain, mockBucketName, GetBucketMetaQuery)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ return req
+ },
+ wantedResult: "0xF72aDa8130f934887755492879496b026665FbABmock-bucket-name010016997810800xF72aDa8130f934887755492879496b026665FbAB300false00xF72aDa8130f934887755492879496b026665FbAB0x21c349a869bde1f44378936e2a9a15ed3fb2d54a43eaea8787960bba1134cdc20x0cbff0ff3831d61345dbfda5b984e254c4bf87ecf80b45ccbb0635c0547a3b1a12798111699781103030x26281179b8885F21f95b0a246c8AD70957A95A230xF72aDa8130f934887755492879496b026665FbAB16997809940240000000000000001000000",
+ },
+ }
+ for _, tt := range cases {
+ t.Run(tt.name, func(t *testing.T) {
+ router := mockGetBucketMetaHandlerRoute(t, tt.fn())
+ w := httptest.NewRecorder()
+ router.ServeHTTP(w, tt.request())
+ if tt.wantedResult != "" {
+ assert.Contains(t, w.Body.String(), tt.wantedResult)
+ }
+ if tt.wantedResultFn != nil {
+ assert.True(t, tt.wantedResultFn(w.Body.String()))
+ }
+ })
+ }
+}
+
+func mockGetUserBucketsHandlerRoute(t *testing.T, g *GateModular) *mux.Router {
+ t.Helper()
+ router := mux.NewRouter().SkipClean(true)
+ router.Path("/").Name(getUserBucketsRouterName).Methods(http.MethodGet).HandlerFunc(g.getUserBucketsHandler)
+
+ return router
+}
+
+func TestGateModular_GetUserBucketsHandler(t *testing.T) {
+
+ cases := []struct {
+ name string
+ fn func() *GateModular
+ request func() *http.Request
+ wantedResult string
+ wantedResultFn func(body string) bool
+ }{
+ {
+ name: "new request context error",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetUserBuckets(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, mockErr).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, testAccount)
+ return req
+ },
+ wantedResult: "mock error",
+ },
+ {
+ name: "invalid user address",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, "invalid_account")
+ return req
+ },
+ wantedResult: "invalid request header",
+ },
+ {
+ name: "wrong requestIncludeRemoved",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/?&&include-removed=invalid", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, testAccount)
+ return req
+ },
+ wantedResult: "invalid request params for query",
+ },
+
+ {
+ name: "xml response",
+ fn: func() *GateModular {
+ g := setup(t)
+ ctrl := gomock.NewController(t)
+ clientMock := gfspclient.NewMockGfSpClientAPI(ctrl)
+ clientMock.EXPECT().GetUserBuckets(gomock.Any(), testAccount, gomock.Any()).Return(getTestVGFInfoBuckets(1), nil).Times(1)
+ g.baseApp.SetGfSpClient(clientMock)
+ return g
+ },
+ request: func() *http.Request {
+ path := fmt.Sprintf("%s%s/", scheme, testDomain)
+ req := httptest.NewRequest(http.MethodGet, path, strings.NewReader(""))
+ req.Header.Set(GnfdUserAddressHeader, testAccount)
+ return req
+ },
+ wantedResult: "0xF72aDa8130f934887755492879496b026665FbABmock-bucket-name010016997810800xF72aDa8130f934887755492879496b026665FbAB300false00xF72aDa8130f934887755492879496b026665FbAB0x21c349a869bde1f44378936e2a9a15ed3fb2d54a43eaea8787960bba1134cdc20x0cbff0ff3831d61345dbfda5b984e254c4bf87ecf80b45ccbb0635c0547a3b1a12798111699781103030x26281179b8885F21f95b0a246c8AD70957A95A23",
+ },
+ }
+ for _, tt := range cases {
+ t.Run(tt.name, func(t *testing.T) {
+ router := mockGetUserBucketsHandlerRoute(t, tt.fn())
+ w := httptest.NewRecorder()
+ router.ServeHTTP(w, tt.request())
+ if tt.wantedResult != "" {
+ assert.Contains(t, w.Body.String(), tt.wantedResult)
+ }
+ if tt.wantedResultFn != nil {
+ assert.True(t, tt.wantedResultFn(w.Body.String()))
+ }
+ })
+ }
+}
diff --git a/modular/metadata/types/metadata_types.go b/modular/metadata/types/metadata_types.go
new file mode 100644
index 000000000..e0bd884f1
--- /dev/null
+++ b/modular/metadata/types/metadata_types.go
@@ -0,0 +1,98 @@
+package types
+
+import (
+ "encoding/base64"
+ "encoding/xml"
+)
+
+func (m GfSpListObjectsByBucketNameResponse) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+ type Alias GfSpListObjectsByBucketNameResponse
+ // Create a new struct with Base64-encoded Checksums field
+ responseAlias := Alias(m)
+ for _, o := range responseAlias.Objects {
+ for i, c := range o.ObjectInfo.Checksums {
+ o.ObjectInfo.Checksums[i] = []byte(base64.StdEncoding.EncodeToString(c))
+ }
+ }
+ return e.EncodeElement(responseAlias, start)
+}
+
+func (m GfSpGetObjectMetaResponse) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+ type Alias GfSpGetObjectMetaResponse
+ // Create a new struct with Base64-encoded Checksums field
+ responseAlias := Alias(m)
+ o := responseAlias.Object
+ for i, c := range o.ObjectInfo.Checksums {
+ o.ObjectInfo.Checksums[i] = []byte(base64.StdEncoding.EncodeToString(c))
+ }
+ return e.EncodeElement(responseAlias, start)
+}
+
+type GroupEntry struct {
+ Id uint64
+ Value *Group
+}
+
+func (m GfSpListGroupsByIDsResponse) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+ if len(m.Groups) == 0 {
+ return nil
+ }
+
+ err := e.EncodeToken(start)
+ if err != nil {
+ return err
+ }
+
+ for k, v := range m.Groups {
+ e.Encode(GroupEntry{Id: k, Value: v})
+ }
+
+ return e.EncodeToken(start.End())
+}
+
+type ObjectEntry struct {
+ Id uint64
+ Value *Object
+}
+
+func (m GfSpListObjectsByIDsResponse) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+ if len(m.Objects) == 0 {
+ return nil
+ }
+
+ err := e.EncodeToken(start)
+ if err != nil {
+ return err
+ }
+
+ for k, o := range m.Objects {
+ for i, c := range o.ObjectInfo.Checksums {
+ o.ObjectInfo.Checksums[i] = []byte(base64.StdEncoding.EncodeToString(c))
+ }
+ e.Encode(ObjectEntry{Id: k, Value: o})
+ }
+
+ return e.EncodeToken(start.End())
+}
+
+type BucketEntry struct {
+ Id uint64
+ Value *Bucket
+}
+
+func (m GfSpListBucketsByIDsResponse) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+ if len(m.Buckets) == 0 {
+ return nil
+ }
+
+ err := e.EncodeToken(start)
+ if err != nil {
+ return err
+ }
+
+ for k, v := range m.Buckets {
+ e.Encode(BucketEntry{Id: k, Value: v})
+ }
+
+ return e.EncodeToken(start.End())
+}
diff --git a/store/bsdb/prefix.go b/store/bsdb/prefix.go
index 5b0b841d5..783178bb1 100644
--- a/store/bsdb/prefix.go
+++ b/store/bsdb/prefix.go
@@ -56,7 +56,7 @@ func (b *BsDBImpl) ListObjects(bucketName, continuationToken, prefix string, max
if err != nil {
return nil, err
}
- res, err = b.filterObjects(nodes)
+ res, err = b.filterObjects(nodes, bucketName)
return res, err
}
@@ -82,7 +82,7 @@ func processPath(pathName string) (string, string) {
// filterObjects filters a slice of SlashPrefixTreeNode for nodes which IsObject attribute is true,
// maps these objects by their ID and transforms them into a ListObjectsResult format.
// Returns a slice of ListObjectsResult containing filtered object data or an error if something goes wrong.
-func (b *BsDBImpl) filterObjects(nodes []*SlashPrefixTreeNode) ([]*ListObjectsResult, error) {
+func (b *BsDBImpl) filterObjects(nodes []*SlashPrefixTreeNode, bucketName string) ([]*ListObjectsResult, error) {
var (
objectIDs []common.Hash
totalObjects []*Object
@@ -108,16 +108,14 @@ func (b *BsDBImpl) filterObjects(nodes []*SlashPrefixTreeNode) ([]*ListObjectsRe
}
}
- for i := 0; i < ObjectsNumberOfShards; i++ {
- err = b.db.Table(GetObjectsTableNameByShardNumber(i)).
- Where("object_id in (?)", objectIDs).
- Find(&objects).Error
- //stop after finding one set?
- if err != nil {
- return nil, err
- }
- totalObjects = append(totalObjects, objects...)
+ err = b.db.Table(GetObjectsTableName(bucketName)).
+ Where("object_id in (?)", objectIDs).
+ Find(&objects).Error
+
+ if err != nil {
+ return nil, err
}
+ totalObjects = append(totalObjects, objects...)
objectsMap = make(map[common.Hash]*Object)
for _, object := range totalObjects {
diff --git a/store/bsdb/prefix_test.go b/store/bsdb/prefix_test.go
index c9ee16e69..df048369b 100644
--- a/store/bsdb/prefix_test.go
+++ b/store/bsdb/prefix_test.go
@@ -31,15 +31,13 @@ func TestBsDBImpl_ListObjectsSuccess(t *testing.T) {
AddRow("testPath1/", "testPath1/obj1", "obj1", true, false, bucketName, common.HexToHash("1"), "obj1").
AddRow("testPath2/", "testPath2/obj2", "obj2", true, false, bucketName, common.HexToHash("2"), "obj2"))
- // Expectations for GetObjectsTableNameByShardNumber
- for i := 0; i < ObjectsNumberOfShards; i++ {
- mock.ExpectQuery(fmt.Sprintf("SELECT * FROM `%s` WHERE object_id in (?,?)", GetObjectsTableNameByShardNumber(i))).
- WithArgs(common.HexToHash("1"), common.HexToHash("2")).
- WillReturnRows(
- sqlmock.NewRows([]string{"object_id", "object_name"}).
- AddRow(common.HexToHash("1"), "obj1").
- AddRow(common.HexToHash("2"), "obj2"))
- }
+ // Expectations for GetObjectsTableName
+ mock.ExpectQuery(fmt.Sprintf("SELECT * FROM `%s` WHERE object_id in (?,?)", GetObjectsTableName(bucketName))).
+ WithArgs(common.HexToHash("1"), common.HexToHash("2")).
+ WillReturnRows(
+ sqlmock.NewRows([]string{"object_id", "object_name"}).
+ AddRow(common.HexToHash("1"), "obj1").
+ AddRow(common.HexToHash("2"), "obj2"))
res, err := s.ListObjects(bucketName, "", prefix, maxKeys)
@@ -67,14 +65,12 @@ func TestBsDBImpl_ListObjectsWithContinuationToken(t *testing.T) {
sqlmock.NewRows([]string{"path_name", "full_name", "name", "is_object", "is_folder", "bucket_name", "object_id", "object_name"}).
AddRow("testPath2/", "testPath2/obj2", "obj2", true, false, bucketName, common.HexToHash("2"), "obj2"))
- // Expectations for GetObjectsTableNameByShardNumber
- for i := 0; i < ObjectsNumberOfShards; i++ {
- mock.ExpectQuery(fmt.Sprintf("SELECT * FROM `%s` WHERE object_id in (?)", GetObjectsTableNameByShardNumber(i))).
- WithArgs(common.HexToHash("2")).
- WillReturnRows(
- sqlmock.NewRows([]string{"object_id", "object_name"}).
- AddRow(common.HexToHash("2"), "obj2"))
- }
+ // Expectations for GetObjectsTableName
+ mock.ExpectQuery(fmt.Sprintf("SELECT * FROM `%s` WHERE object_id in (?)", GetObjectsTableName(bucketName))).
+ WithArgs(common.HexToHash("2")).
+ WillReturnRows(
+ sqlmock.NewRows([]string{"object_id", "object_name"}).
+ AddRow(common.HexToHash("2"), "obj2"))
res, err := s.ListObjects(bucketName, continuationToken, prefix, maxKeys)
@@ -97,12 +93,10 @@ func TestBsDBImpl_ListObjectsWithEmptyResult(t *testing.T) {
WithArgs(bucketName, prefix).
WillReturnRows(sqlmock.NewRows([]string{"path_name", "full_name", "name", "is_object", "is_folder", "bucket_name", "object_id", "object_name"}))
- for i := 0; i < ObjectsNumberOfShards; i++ {
- mock.ExpectQuery(fmt.Sprintf("SELECT * FROM `%s` WHERE object_id in (?)", GetObjectsTableNameByShardNumber(i))).
- WithArgs(sqlmock.AnyArg()).
- WillReturnRows(
- sqlmock.NewRows([]string{"object_id", "object_name"}))
- }
+ mock.ExpectQuery(fmt.Sprintf("SELECT * FROM `%s` WHERE object_id in (?)", GetObjectsTableName(bucketName))).
+ WithArgs(sqlmock.AnyArg()).
+ WillReturnRows(
+ sqlmock.NewRows([]string{"object_id", "object_name"}))
res, err := s.ListObjects(bucketName, "", prefix, maxKeys)
assert.Nil(t, err)
@@ -142,13 +136,11 @@ func TestBsDBImpl_ListObjectsWithPathName(t *testing.T) {
sqlmock.NewRows([]string{"path_name", "full_name", "name", "is_object", "is_folder", "bucket_name", "object_id", "object_name"}).
AddRow("testPath2/", "testPath2/obj2", "obj2", true, false, bucketName, common.HexToHash("2"), "obj2"))
- for i := 0; i < ObjectsNumberOfShards; i++ {
- mock.ExpectQuery(fmt.Sprintf("SELECT * FROM `%s` WHERE object_id in (?)", GetObjectsTableNameByShardNumber(i))).
- WithArgs(common.HexToHash("2")).
- WillReturnRows(
- sqlmock.NewRows([]string{"object_id", "object_name"}).
- AddRow(common.HexToHash("2"), "obj2"))
- }
+ mock.ExpectQuery(fmt.Sprintf("SELECT * FROM `%s` WHERE object_id in (?)", GetObjectsTableName(bucketName))).
+ WithArgs(common.HexToHash("2")).
+ WillReturnRows(
+ sqlmock.NewRows([]string{"object_id", "object_name"}).
+ AddRow(common.HexToHash("2"), "obj2"))
res, err := s.ListObjects(bucketName, "", prefix, maxKeys)
assert.Nil(t, err)
@@ -178,13 +170,11 @@ func TestBsDBImpl_ListObjectsWithPrefixQuery(t *testing.T) {
AddRow("testPath2", "testPath2/obj2", "obj2", true, false, bucketName, common.HexToHash("2"), "obj2"))
// Set expectation for the object details query on the respective objects_xx table
- for i := 0; i < ObjectsNumberOfShards; i++ {
- mock.ExpectQuery(fmt.Sprintf("SELECT * FROM `%s` WHERE object_id in (?)", GetObjectsTableNameByShardNumber(i))).
- WithArgs(common.HexToHash("2")).
- WillReturnRows(
- sqlmock.NewRows([]string{"object_id", "object_name"}).
- AddRow(common.HexToHash("2"), "obj2"))
- }
+ mock.ExpectQuery(fmt.Sprintf("SELECT * FROM `%s` WHERE object_id in (?)", GetObjectsTableName(bucketName))).
+ WithArgs(common.HexToHash("2")).
+ WillReturnRows(
+ sqlmock.NewRows([]string{"object_id", "object_name"}).
+ AddRow(common.HexToHash("2"), "obj2"))
res, err := s.ListObjects(bucketName, "", prefix, maxKeys)
assert.Nil(t, err)
@@ -213,13 +203,11 @@ func TestBsDBImpl_ListObjectsWithAllConditions(t *testing.T) {
sqlmock.NewRows([]string{"path_name", "full_name", "name", "is_object", "is_folder", "bucket_name", "object_id", "object_name"}).
AddRow("testPath2", "testPath2/obj2", "obj2", true, false, bucketName, common.HexToHash("2"), "obj2"))
- for i := 0; i < ObjectsNumberOfShards; i++ {
- mock.ExpectQuery(fmt.Sprintf("SELECT * FROM `%s` WHERE object_id in (?)", GetObjectsTableNameByShardNumber(i))).
- WithArgs(common.HexToHash("2")).
- WillReturnRows(
- sqlmock.NewRows([]string{"object_id", "object_name"}).
- AddRow(common.HexToHash("2"), "obj2"))
- }
+ mock.ExpectQuery(fmt.Sprintf("SELECT * FROM `%s` WHERE object_id in (?)", GetObjectsTableName(bucketName))).
+ WithArgs(common.HexToHash("2")).
+ WillReturnRows(
+ sqlmock.NewRows([]string{"object_id", "object_name"}).
+ AddRow(common.HexToHash("2"), "obj2"))
res, err := s.ListObjects(bucketName, continuationToken, prefix, maxKeys)
assert.Nil(t, err)