diff --git a/build/builder.go b/build/builder.go index ad0ea42..4e6a790 100644 --- a/build/builder.go +++ b/build/builder.go @@ -15,6 +15,7 @@ import ( "github.com/filecoin-project/venus-wallet/storage/strategy" "github.com/filecoin-project/venus-wallet/storage/wallet" "github.com/filecoin-project/venus-wallet/wallet_event" + "github.com/gbrlsnchs/jwt/v3" "github.com/ipfs-force-community/venus-gateway/types" "go.uber.org/fx" @@ -84,9 +85,9 @@ func WalletOpt(repo filemgr.Repo, walletPwd string) Option { ) } -func CommonOpt(alg *common.APIAlg) Option { +func CommonOpt(alg *jwt.HMACSHA) Option { return Options( - Override(new(*common.APIAlg), alg), + Override(new(*jwt.HMACSHA), alg), Override(new(common.ICommon), From(new(common.Common))), ) } diff --git a/cmd/daemon.go b/cmd/daemon.go index a8417a7..31c9c27 100644 --- a/cmd/daemon.go +++ b/cmd/daemon.go @@ -94,6 +94,6 @@ var RunCmd = &cli.Command{ } // TODO: properly parse api endpoint (or make it a URL) - return ServeRPC(fullAPI, stop, endpoint) + return ServeRPC(fullAPI, stop, endpoint, nil) }, } diff --git a/cmd/mock/main.go b/cmd/mock/main.go index 6a597d7..3ad82fb 100644 --- a/cmd/mock/main.go +++ b/cmd/mock/main.go @@ -75,7 +75,7 @@ func main() { log.Println("Pre-preparation completed") // TODO: properly parse api endpoint (or make it a URL) // Use serveRPC method to perform local CLI debugging - err = cmd.ServeRPC(fullAPI, stop, endpoint) + err = cmd.ServeRPC(fullAPI, stop, endpoint, nil) if err != nil { log.Fatal(err) } diff --git a/cmd/rpc.go b/cmd/rpc.go index 8afdd89..d6f80db 100644 --- a/cmd/rpc.go +++ b/cmd/rpc.go @@ -40,8 +40,8 @@ func CorsMiddleWare(next http.Handler) http.Handler { }) } -// Start the interface service and bind the address -func ServeRPC(a api.IFullAPI, stop build.StopFunc, addr string) error { +// ServeRPC Start the interface service and bind the address +func ServeRPC(a api.IFullAPI, stop build.StopFunc, addr string, sigChan chan os.Signal) error { rpcServer := jsonrpc.NewServer() rpcServer.Register("Filecoin", permissionedFullAPI(a)) ah := &Handler{ @@ -58,7 +58,9 @@ func ServeRPC(a api.IFullAPI, stop build.StopFunc, addr string) error { return fmt.Errorf("could not listen: %w", err) } srv := &http.Server{Handler: http.DefaultServeMux} - sigChan := make(chan os.Signal, 2) + if sigChan == nil { + sigChan = make(chan os.Signal, 2) + } go func() { <-sigChan if err := srv.Shutdown(context.TODO()); err != nil { diff --git a/common/api_common.go b/common/api_common.go index 28ae5cb..45cfb38 100644 --- a/common/api_common.go +++ b/common/api_common.go @@ -15,13 +15,11 @@ import ( type ICommon = api.ICommon -type APIAlg jwt.HMACSHA - var _ ICommon = &Common{} type Common struct { fx.In - APISecret *APIAlg + APISecret *jwt.HMACSHA } type jwtPayload struct { @@ -30,7 +28,7 @@ type jwtPayload struct { func (a *Common) AuthVerify(ctx context.Context, token string) ([]auth.Permission, error) { var payload jwtPayload - if _, err := jwt.Verify([]byte(token), (*jwt.HMACSHA)(a.APISecret), &payload); err != nil { + if _, err := jwt.Verify([]byte(token), a.APISecret, &payload); err != nil { return nil, fmt.Errorf("JWT Verification failed: %w", err) } return payload.Allow, nil @@ -40,7 +38,7 @@ func (a *Common) AuthNew(ctx context.Context, perms []auth.Permission) ([]byte, p := jwtPayload{ Allow: perms, // TODO: consider checking validity } - return jwt.Sign(&p, (*jwt.HMACSHA)(a.APISecret)) + return jwt.Sign(&p, a.APISecret) } func (a *Common) Version(context.Context) (types.Version, error) { diff --git a/common/api_common_test.go b/common/api_common_test.go new file mode 100644 index 0000000..d50495c --- /dev/null +++ b/common/api_common_test.go @@ -0,0 +1,71 @@ +//stm: #unit +package common + +import ( + "context" + "encoding/hex" + "reflect" + "testing" + + "github.com/filecoin-project/go-jsonrpc/auth" + "github.com/filecoin-project/venus-wallet/filemgr" + "github.com/gbrlsnchs/jwt/v3" + "github.com/stretchr/testify/require" + "go.uber.org/fx" + "go.uber.org/fx/fxtest" +) + +func TestCommon_AuthVerify(t *testing.T) { + //stm: @VENUSWALLET_API_COMMON_AUTH_VERIFY_001, @VENUSWALLET_API_COMMON_AUTH_NEW_001 + t.Parallel() + var c Common + + cng, err := filemgr.RandJWTConfig() + require.NoError(t, err) + sec, err := hex.DecodeString(cng.Secret) + require.NoError(t, err) + + app := fxtest.New(t, + fx.Provide(func() *jwt.HMACSHA { return jwt.NewHS256(sec) }), + fx.Populate(&c), + ) + defer app.RequireStart().RequireStop() + + type args struct { + token string + } + + type testCase struct { + args args + want []auth.Permission + wantErr bool + } + + tests := map[string]*testCase{ + "invalid-token-verify": {args: args{"invalid-token"}, want: nil, wantErr: true}, + } + + ctx := context.Background() + + validTokenCase := &testCase{want: []auth.Permission{"admin", "sign", "write"}, wantErr: false} + token, err := c.AuthNew(ctx, validTokenCase.want) + require.NoError(t, err) + validTokenCase.args.token = string(token) + + tests["valid-token-verify"] = validTokenCase + + for tName, tt := range tests { + t.Run(tName, func(t *testing.T) { + got, err := c.AuthVerify(ctx, tt.args.token) + + if (err != nil) != tt.wantErr { + t.Errorf("AuthVerify() error = %v, wantErr %v", err, tt.wantErr) + return + } + + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("AuthVerify() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/filemgr/fs.go b/filemgr/fs.go index e3aaa90..74c8c6b 100644 --- a/filemgr/fs.go +++ b/filemgr/fs.go @@ -9,7 +9,6 @@ import ( "path/filepath" "strings" - "github.com/filecoin-project/venus-wallet/common" "github.com/filecoin-project/venus-wallet/config" "github.com/filecoin-project/venus-wallet/crypto/aes" jwt "github.com/gbrlsnchs/jwt/v3" @@ -59,12 +58,12 @@ func NewFS(path string, op *OverrideParams) (Repo, error) { } return fs, nil } -func (fsr *FsRepo) APISecret() (*common.APIAlg, error) { +func (fsr *FsRepo) APISecret() (*jwt.HMACSHA, error) { sec, err := hex.DecodeString(fsr.cnf.JWT.Secret) if err != nil { return nil, err } - return (*common.APIAlg)(jwt.NewHS256(sec)), nil + return jwt.NewHS256(sec), nil } func (fsr *FsRepo) init() error { exist, err := fsr.exists() diff --git a/filemgr/fs_test.go b/filemgr/fs_test.go index d729cf0..48e4c16 100644 --- a/filemgr/fs_test.go +++ b/filemgr/fs_test.go @@ -1,3 +1,4 @@ +//stm: #unit package filemgr import ( @@ -5,10 +6,12 @@ import ( "os" "testing" + "github.com/stretchr/testify/require" "gotest.tools/assert" ) func TestNewFS(t *testing.T) { + //stm: @VENUSWALLET_FILEMGR_FS_NEW_001 fsPath, err := ioutil.TempDir("", "venus-repo-") defer os.RemoveAll(fsPath) if err != nil { @@ -18,9 +21,19 @@ func TestNewFS(t *testing.T) { fs, err := NewFS(fsPath, &OverrideParams{ API: targetAPI, }) - if err != nil { - t.Fatal(err) - } + require.NoError(t, err) + require.NotNil(t, fs) + + //stm: @VENUSWALLET_FILEMGR_FS_API_SECRET_001, + secr, err := fs.APISecret() + require.NoError(t, err) + require.NotNil(t, secr) + + //stm: @VENUSWALLET_FILEMGR_FS_API_STRATEGY_TOKEN_001 + token, err := fs.APIStrategyToken("password") + require.NoError(t, err) + require.NotEqual(t, token, "") + curAPI, err := fs.APIEndpoint() if err != nil { t.Fatal() diff --git a/filemgr/interface.go b/filemgr/interface.go index e505db4..5f897c9 100644 --- a/filemgr/interface.go +++ b/filemgr/interface.go @@ -1,8 +1,8 @@ package filemgr import ( - "github.com/filecoin-project/venus-wallet/common" "github.com/filecoin-project/venus-wallet/config" + "github.com/gbrlsnchs/jwt/v3" ) // file system @@ -13,7 +13,7 @@ type Repo interface { // APIToken returns JWT API Token for use in operations that require auth APIToken() ([]byte, error) - APISecret() (*common.APIAlg, error) + APISecret() (*jwt.HMACSHA, error) // APIStrategyToken cli pwd convert root token APIStrategyToken(password string) (string, error) diff --git a/filemgr/jwt.go b/filemgr/jwt.go index 87ac893..0477520 100644 --- a/filemgr/jwt.go +++ b/filemgr/jwt.go @@ -39,10 +39,6 @@ func randSecret() (*jwtSecret, error) { }, nil } -/*func (js *jwtSecret) alg() *api.APIAlg { - return (*api.APIAlg)(jwt.NewHS256(js.key)) -}*/ - // Random generation of JWT config func RandJWTConfig() (*config.JWTConfig, error) { js, err := randSecret() diff --git a/integration_test/builder.go b/integration_test/builder.go new file mode 100644 index 0000000..31e9426 --- /dev/null +++ b/integration_test/builder.go @@ -0,0 +1,123 @@ +package integration + +import ( + "context" + "fmt" + "io/ioutil" + "os" + "strings" + "syscall" + "time" + + "github.com/filecoin-project/venus-wallet/api" + "github.com/filecoin-project/venus-wallet/build" + "github.com/filecoin-project/venus-wallet/cmd" + "github.com/filecoin-project/venus-wallet/core" + "github.com/filecoin-project/venus-wallet/filemgr" + "github.com/filecoin-project/venus-wallet/middleware" + "github.com/filecoin-project/venus-wallet/version" + logging "github.com/ipfs/go-log/v2" + "github.com/multiformats/go-multiaddr" + "go.opencensus.io/stats" + "go.opencensus.io/stats/view" + "go.opencensus.io/tag" +) + +var log = logging.Logger("wallet_instance") + +type WalletInst struct { + repo filemgr.Repo + repoDir string + + stopChan chan error + sigChan chan os.Signal +} + +func (inst *WalletInst) Start() (string, error) { + secret, err := inst.repo.APISecret() + if err != nil { + return "", err + } + + var fullAPI api.IFullAPI + var appStopFn build.StopFunc + + ctx, _ := tag.New(context.Background(), tag.Insert(middleware.Version, version.BuildVersion)) + + if appStopFn, err = build.New(ctx, build.FullAPIOpt(&fullAPI), + build.WalletOpt(inst.repo, ""), + build.CommonOpt(secret)); err != nil { + return "", err + } + + // Register all metric views + if err = view.Register( + middleware.DefaultViews..., + ); err != nil { + return "", fmt.Errorf("can't register the view: %v", err) + } + stats.Record(ctx, middleware.VenusInfo.M(1)) + + endPoint, err := inst.repo.APIEndpoint() + if err != nil { + return "", fmt.Errorf("get api endpoint failed:%w", err) + } + + ma, err := multiaddr.NewMultiaddr(endPoint) + if err != nil { + return "", fmt.Errorf("new multi-address failed:%w", err) + } + + url, err := ToURL(ma) + if err != nil { + return "", fmt.Errorf("convert multi-addr:%s to url failed:%w", endPoint, err) + } + + go func() { + err := cmd.ServeRPC(fullAPI, appStopFn, endPoint, inst.sigChan) + inst.stopChan <- err + }() + + return url.String(), inst.checkService() +} + +func (inst *WalletInst) checkService() error { + select { + case err := <-inst.stopChan: + return err + case <-time.After(time.Second): + log.Info("no signal from stopping channel, after 1 second waitting...") + } + return nil +} + +func (inst *WalletInst) StopAndWait() error { + inst.sigChan <- syscall.SIGINT + for { + if err := inst.checkService(); err != nil { + // server close is not an error + if strings.ContainsAny(err.Error(), "server closed") { + return nil + } + return err + } + } +} + +func NewWalletInst() (*WalletInst, error) { + dir, err := ioutil.TempDir("", "venus_wallet_") + if err != nil { + return nil, err + + } + repo, err := filemgr.NewFS(dir, nil) + if err != nil { + return nil, err + } + core.WalletStrategyLevel = repo.Config().Strategy.Level + return &WalletInst{ + repo: repo, + sigChan: make(chan os.Signal, 1), + stopChan: make(chan error, 1), + repoDir: dir}, nil +} diff --git a/integration_test/convert.go b/integration_test/convert.go new file mode 100644 index 0000000..eb3fd2d --- /dev/null +++ b/integration_test/convert.go @@ -0,0 +1,139 @@ +package integration + +/* + This file is totally carried from : + github.com/filecoin-project/go-legs/httpsync/multiaddr/convert.go +*/ + +import ( + "bytes" + "fmt" + "net" + "net/url" + + "github.com/multiformats/go-multiaddr" + manet "github.com/multiformats/go-multiaddr/net" +) + +// register an 'httpath' component: +var transcodePath = multiaddr.NewTranscoderFromFunctions(pathStB, pathBtS, pathVal) + +func pathVal(b []byte) error { + if bytes.IndexByte(b, '/') >= 0 { + return fmt.Errorf("encoded path '%s' contains a slash", string(b)) + } + return nil +} + +func pathStB(s string) ([]byte, error) { + return []byte(s), nil +} + +func pathBtS(b []byte) (string, error) { + return string(b), nil +} + +func init() { + _ = multiaddr.AddProtocol(protoHTTPath) +} + +var protoHTTPath = multiaddr.Protocol{ + Name: "httpath", + Code: 0x300200, + VCode: multiaddr.CodeToVarint(0x300200), + Size: multiaddr.LengthPrefixedVarSize, + Transcoder: transcodePath, +} + +// ToURL takes a multiaddr of the form: +// /dns/thing.com/http/urlescape +// /ip/192.168.0.1/tcp/80/http +func ToURL(ma multiaddr.Multiaddr) (*url.URL, error) { + // host should be either the dns name or the IP + _, host, err := manet.DialArgs(ma) + if err != nil { + return nil, err + } + if ip := net.ParseIP(host); ip != nil { + if !ip.To4().Equal(ip) { + // raw v6 IPs need `[ip]` encapsulation. + host = fmt.Sprintf("[%s]", host) + } + } + + protos := ma.Protocols() + pm := make(map[int]string, len(protos)) + for _, p := range protos { + v, err := ma.ValueForProtocol(p.Code) + if err == nil { + pm[p.Code] = v + } + } + + scheme := "http" + if _, ok := pm[multiaddr.P_HTTPS]; ok { + scheme = "https" + } // todo: ws/wss + + path := "" + if pb, ok := pm[protoHTTPath.Code]; ok { + path, err = url.PathUnescape(pb) + if err != nil { + path = "" + } + } + + out := url.URL{ + Scheme: scheme, + Host: host, + Path: path, + } + return &out, nil +} + +// ToMA takes a url and converts it into a multiaddr. +// converts scheme://host:port/path -> /ip/host/tcp/port/scheme/urlescape{path} +func ToMA(u *url.URL) (*multiaddr.Multiaddr, error) { + h := u.Hostname() + var addr *multiaddr.Multiaddr + if n := net.ParseIP(h); n != nil { + ipAddr, err := manet.FromIP(n) + if err != nil { + return nil, err + } + addr = &ipAddr + } else { + // domain name + ma, err := multiaddr.NewComponent(multiaddr.ProtocolWithCode(multiaddr.P_DNS).Name, h) + if err != nil { + return nil, err + } + mab := multiaddr.Cast(ma.Bytes()) + addr = &mab + } + pv := u.Port() + if pv != "" { + port, err := multiaddr.NewComponent(multiaddr.ProtocolWithCode(multiaddr.P_TCP).Name, pv) + if err != nil { + return nil, err + } + wport := multiaddr.Join(*addr, port) + addr = &wport + } + + http, err := multiaddr.NewComponent(u.Scheme, "") + if err != nil { + return nil, err + } + + joint := multiaddr.Join(*addr, http) + if u.Path != "" { + httpath, err := multiaddr.NewComponent(protoHTTPath.Name, url.PathEscape(u.Path)) + if err != nil { + return nil, err + } + joint = multiaddr.Join(joint, httpath) + } + + return &joint, nil +} diff --git a/integration_test/integration_test.go b/integration_test/integration_test.go new file mode 100644 index 0000000..4f3713c --- /dev/null +++ b/integration_test/integration_test.go @@ -0,0 +1,140 @@ +//stm: #integration +package integration + +import ( + "context" + "flag" + "fmt" + "os" + "testing" + + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/venus/venus-shared/types" + + "github.com/filecoin-project/go-jsonrpc" + api2 "github.com/filecoin-project/venus-wallet/api" + "github.com/stretchr/testify/require" + + "github.com/filecoin-project/venus-wallet/cli/helper" + + "github.com/urfave/cli/v2" +) + +var ( + inst *WalletInst + client api2.IFullAPI + clientCloser jsonrpc.ClientCloser + defaultWalletPwd = "default-wallet-pwd" +) + +func setup() error { + var err error + var url string + if inst, err = NewWalletInst(); err != nil { + return err + } + if url, err = inst.Start(); err != nil { + return err + } + + log.Infof("Wallet instance listen on endpoint: %s", url) + + flags := flag.NewFlagSet("", flag.PanicOnError) + flags.String("repo", inst.repoDir, "") + + client, clientCloser, err = helper.GetFullAPI(cli.NewContext(nil, flags, nil)) + return err +} + +func shutDown() error { + defer func() { + if err := os.RemoveAll(inst.repoDir); err != nil { + log.Errorf("remove repo dir:%s failed:%s", inst.repoDir, err.Error()) + } + }() + + clientCloser() + return inst.StopAndWait() +} + +func TestMain(m *testing.M) { + //stm: @VENUSWALLET_NODE_NEW_NODE_CLIENT_001 + if err := setup(); err != nil { + panic(fmt.Sprintf("setup ingeration test failed:%v", err)) + } + + exitCode := m.Run() + + if err := shutDown(); err != nil { + panic(fmt.Sprintf("shutdown ingeration test failed:%v", err)) + } + + os.Exit(exitCode) +} + +func TestWallet(t *testing.T) { + //stm: @VENUSWALLET_STORAGE_KEYMIX_SET_PASSWORD_001, @VENUSWALLET_STORAGE_WALLET_SET_PASSWORD_001 + t.Run("wallet setPwd/unlock", testWalletSetPassword) + + //stm: @VENUSWALLET_STORAGE_SQLITE_KEY_STORE_PUT_001, @VENUSWALLET_STORAGE_SQLITE_KEY_STORE_HAS_001, + //stm: @VENUSWALLET_STORAGE_SQLITE_KEY_STORE_LIST_001, @VENUSWALLET_STORAGE_SQLITE_KEY_STORE_DELETE_001, @VENUSWALLET_STORAGE_SQLITE_KEY_STORE_GET_001 + //stm: @VENUSWALLET_STORAGE_WALLET_WALLET_NEW_001, @VENUSWALLET_STORAGE_WALLET_WALLET_LIST_001 + t.Run("wallet address", testWalletAddress) +} + +func testWalletSetPassword(t *testing.T) { + ctx := context.TODO() + if err := client.SetPassword(ctx, defaultWalletPwd); err != nil { + require.Contains(t, err.Error(), "already have") + } + + if err := client.Unlock(ctx, defaultWalletPwd); err != nil { + require.Contains(t, err.Error(), "already unlock") + } +} + +func testWalletAddress(t *testing.T) { + ctx := context.TODO() + + var newAddrs = make(map[address.Address]struct{}) + var err error + + blsAddr, err := client.WalletNew(ctx, types.KTBLS) + require.NoError(t, err) + newAddrs[blsAddr] = struct{}{} + + secpAddr, err := client.WalletNew(ctx, types.KTSecp256k1) + require.NoError(t, err) + newAddrs[secpAddr] = struct{}{} + + addrList, err := client.WalletList(ctx) + require.NoError(t, err) + + var totalAddrs = make(map[address.Address]struct{}) + for _, a := range addrList { + totalAddrs[a] = struct{}{} + } + + for addr := range newAddrs { + _, isok := totalAddrs[addr] + require.True(t, isok, true) + + isok, err = client.WalletHas(ctx, addr) + require.NoError(t, err) + require.True(t, isok) + } + + require.NoError(t, client.Lock(ctx, defaultWalletPwd)) + + // call unlock for covering `store.sqlite.sqliteStorage.Get` + require.NoError(t, client.Unlock(ctx, defaultWalletPwd)) + + // for covering `store.sqlite.sqliteStorage.Delete` + deleteAddr, err := client.WalletNew(ctx, types.KTBLS) + require.NoError(t, err) + require.NoError(t, client.WalletDelete(ctx, deleteAddr)) + // after delete this `deleteAddr`, `WalletHas` should returns us a `false` + has, err := client.WalletHas(ctx, deleteAddr) + require.NoError(t, err) + require.False(t, has) +} diff --git a/storage/sqlite/strategy_store_test.go b/storage/sqlite/strategy_store_test.go index 4ef17f9..eb70a89 100644 --- a/storage/sqlite/strategy_store_test.go +++ b/storage/sqlite/strategy_store_test.go @@ -1,3 +1,4 @@ +//stm: #unit package sqlite import ( @@ -14,6 +15,7 @@ import ( func TestRouterStore_PutMsgTypeTemplate(t *testing.T) { mockName := "mockTest" // MsgTypeTemplate test + //stm: @VENUSWALLET_STORAGE_SQLITE_STRATEGY_NEW_MSG_TYPE_001 mtt := &types.MsgTypeTemplate{ Name: mockName, MetaTypes: 127, @@ -26,12 +28,14 @@ func TestRouterStore_PutMsgTypeTemplate(t *testing.T) { if err != nil { t.Fatalf("GetMsgTypeTemplateByName err:%s", err) } + //stm: @VENUSWALLET_STORAGE_SQLITE_STRATEGY_GET_MSG_TYPE_001 mttById, err := mockRouterStore.GetMsgTypeTemplate(mttByName.MTTId) if err != nil { t.Fatalf("GetMsgTypeTemplate err:%s", err) } assert.DeepEqual(t, mttById, mttByName) + //stm: @VENUSWALLET_STORAGE_SQLITE_STRATEGY_LIST_MSG_TYPE_001 mttArr, err := mockRouterStore.ListMsgTypeTemplates(0, 10) if err != nil { t.Fatalf("ListMethodTemplates err:%s", err) diff --git a/storage/strategy/cache_test.go b/storage/strategy/cache_test.go index 84034c1..ec6264a 100644 --- a/storage/strategy/cache_test.go +++ b/storage/strategy/cache_test.go @@ -1,3 +1,4 @@ +//stm: #unit package strategy import ( @@ -18,6 +19,7 @@ func TestCacheFlow(t *testing.T) { Name: "kb1", Address: addr1, } + //stm: @VENUSWALLET_STORAGE_SQLITE_STRATEGY_CACHE_SET_001 cache.set(tk1, kb1) kbTmp1 := cache.get(tk1, addr1) // Check the query is correct @@ -77,6 +79,7 @@ func TestCacheFlow(t *testing.T) { // tk3 addr2 kb3 // tk1 addr2 kb5 + //stm: @VENUSWALLET_STORAGE_SQLITE_STRATEGY_CACHE_REMOVE_001 cache.remove(tk2, addr1) kbTmp2 = cache.get(tk2, addr1) if kbTmp2 != nil { @@ -116,6 +119,7 @@ func TestCacheFlow(t *testing.T) { // tk3 addr2 kb3 x // tk1 addr2 kb5 x // tk1 addr2 kb6 + //stm: @VENUSWALLET_STORAGE_SQLITE_STRATEGY_CACHE_REMOVE_ST_TOKEN_001 cache.removeStToken(tk1) kb1 = cache.get(tk1, addr1) kb6 = cache.get(tk1, addr2) @@ -129,6 +133,20 @@ func TestCacheFlow(t *testing.T) { // tk1 addr2 kb6 x assert.Equal(t, len(cache.(*strategyCache).kbCache), 0) + //stm: @VENUSWALLET_STORAGE_SQLITE_STRATEGY_CACHE_REMOVE_TOKENS_001 + cache.removeTokens([]string{tk2, tk3}) + assert.Equal(t, len(cache.(*strategyCache).cache), 0) + + //stm: @VENUSWALLET_STORAGE_SQLITE_STRATEGY_CACHE_SET_BLANK_001 + cache.setBlank(tk1, addr1) + _, exist := cache.(*strategyCache).blank[tk1+addr1] + assert.Equal(t, exist, true) + + //stm: @VENUSWALLET_STORAGE_SQLITE_STRATEGY_CACHE_REMOVE_BLANK_001 + cache.removeBlank(tk1, addr1) + _, exist = cache.(*strategyCache).blank[tk1+addr1] + assert.Equal(t, exist, false) + KeyBinds(cache, t) }