diff options
Diffstat (limited to 'cmd/swarm/global-store')
-rw-r--r-- | cmd/swarm/global-store/explorer.go | 66 | ||||
-rw-r--r-- | cmd/swarm/global-store/explorer_test.go | 254 | ||||
-rw-r--r-- | cmd/swarm/global-store/global_store.go | 120 | ||||
-rw-r--r-- | cmd/swarm/global-store/global_store_test.go | 207 | ||||
-rw-r--r-- | cmd/swarm/global-store/main.go | 124 | ||||
-rw-r--r-- | cmd/swarm/global-store/run_test.go | 49 |
6 files changed, 0 insertions, 820 deletions
diff --git a/cmd/swarm/global-store/explorer.go b/cmd/swarm/global-store/explorer.go deleted file mode 100644 index 634ff1ebb..000000000 --- a/cmd/swarm/global-store/explorer.go +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// go-ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. - -package main - -import ( - "context" - "fmt" - "net" - "net/http" - "time" - - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/swarm/storage/mock" - "github.com/ethereum/go-ethereum/swarm/storage/mock/explorer" - cli "gopkg.in/urfave/cli.v1" -) - -// serveChunkExplorer starts an http server in background with chunk explorer handler -// using the provided global store. Server is started if the returned shutdown function -// is not nil. -func serveChunkExplorer(ctx *cli.Context, globalStore mock.GlobalStorer) (shutdown func(), err error) { - if !ctx.IsSet("explorer-address") { - return nil, nil - } - - corsOrigins := ctx.StringSlice("explorer-cors-origin") - server := &http.Server{ - Handler: explorer.NewHandler(globalStore, corsOrigins), - IdleTimeout: 30 * time.Minute, - ReadTimeout: 2 * time.Minute, - WriteTimeout: 2 * time.Minute, - } - listener, err := net.Listen("tcp", ctx.String("explorer-address")) - if err != nil { - return nil, fmt.Errorf("explorer: %v", err) - } - log.Info("chunk explorer http", "address", listener.Addr().String(), "origins", corsOrigins) - - go func() { - if err := server.Serve(listener); err != nil { - log.Error("chunk explorer", "err", err) - } - }() - - return func() { - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - if err := server.Shutdown(ctx); err != nil { - log.Error("chunk explorer: shutdown", "err", err) - } - }, nil -} diff --git a/cmd/swarm/global-store/explorer_test.go b/cmd/swarm/global-store/explorer_test.go deleted file mode 100644 index 2e4928c8f..000000000 --- a/cmd/swarm/global-store/explorer_test.go +++ /dev/null @@ -1,254 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// go-ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. - -package main - -import ( - "encoding/json" - "fmt" - "net/http" - "sort" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/swarm/storage/mock/explorer" - mockRPC "github.com/ethereum/go-ethereum/swarm/storage/mock/rpc" -) - -// TestExplorer validates basic chunk explorer functionality by storing -// a small set of chunk and making http requests on exposed endpoint. -// Full chunk explorer validation is done in mock/explorer package. -func TestExplorer(t *testing.T) { - addr := findFreeTCPAddress(t) - explorerAddr := findFreeTCPAddress(t) - testCmd := runGlobalStore(t, "ws", "--addr", addr, "--explorer-address", explorerAddr) - defer testCmd.Kill() - - client := websocketClient(t, addr) - - store := mockRPC.NewGlobalStore(client) - defer store.Close() - - nodeKeys := map[string][]string{ - "a1": {"b1", "b2", "b3"}, - "a2": {"b3", "b4", "b5"}, - } - - keyNodes := make(map[string][]string) - - for addr, keys := range nodeKeys { - for _, key := range keys { - keyNodes[key] = append(keyNodes[key], addr) - } - } - - invalidAddr := "c1" - invalidKey := "d1" - - for addr, keys := range nodeKeys { - for _, key := range keys { - err := store.Put(common.HexToAddress(addr), common.Hex2Bytes(key), []byte("data")) - if err != nil { - t.Fatal(err) - } - } - } - - endpoint := "http://" + explorerAddr - - t.Run("has key", func(t *testing.T) { - for addr, keys := range nodeKeys { - for _, key := range keys { - testStatusResponse(t, endpoint+"/api/has-key/"+addr+"/"+key, http.StatusOK) - testStatusResponse(t, endpoint+"/api/has-key/"+invalidAddr+"/"+key, http.StatusNotFound) - } - testStatusResponse(t, endpoint+"/api/has-key/"+addr+"/"+invalidKey, http.StatusNotFound) - } - testStatusResponse(t, endpoint+"/api/has-key/"+invalidAddr+"/"+invalidKey, http.StatusNotFound) - }) - - t.Run("keys", func(t *testing.T) { - var keys []string - for key := range keyNodes { - keys = append(keys, key) - } - sort.Strings(keys) - testKeysResponse(t, endpoint+"/api/keys", explorer.KeysResponse{ - Keys: keys, - }) - }) - - t.Run("nodes", func(t *testing.T) { - var nodes []string - for addr := range nodeKeys { - nodes = append(nodes, common.HexToAddress(addr).Hex()) - } - sort.Strings(nodes) - testNodesResponse(t, endpoint+"/api/nodes", explorer.NodesResponse{ - Nodes: nodes, - }) - }) - - t.Run("node keys", func(t *testing.T) { - for addr, keys := range nodeKeys { - testKeysResponse(t, endpoint+"/api/keys?node="+addr, explorer.KeysResponse{ - Keys: keys, - }) - } - testKeysResponse(t, endpoint+"/api/keys?node="+invalidAddr, explorer.KeysResponse{}) - }) - - t.Run("key nodes", func(t *testing.T) { - for key, addrs := range keyNodes { - var nodes []string - for _, addr := range addrs { - nodes = append(nodes, common.HexToAddress(addr).Hex()) - } - sort.Strings(nodes) - testNodesResponse(t, endpoint+"/api/nodes?key="+key, explorer.NodesResponse{ - Nodes: nodes, - }) - } - testNodesResponse(t, endpoint+"/api/nodes?key="+invalidKey, explorer.NodesResponse{}) - }) -} - -// TestExplorer_CORSOrigin validates if chunk explorer returns -// correct CORS origin header in GET and OPTIONS requests. -func TestExplorer_CORSOrigin(t *testing.T) { - origin := "http://localhost/" - addr := findFreeTCPAddress(t) - explorerAddr := findFreeTCPAddress(t) - testCmd := runGlobalStore(t, "ws", - "--addr", addr, - "--explorer-address", explorerAddr, - "--explorer-cors-origin", origin, - ) - defer testCmd.Kill() - - // wait until the server is started - waitHTTPEndpoint(t, explorerAddr) - - url := "http://" + explorerAddr + "/api/keys" - - t.Run("get", func(t *testing.T) { - req, err := http.NewRequest(http.MethodGet, url, nil) - if err != nil { - t.Fatal(err) - } - req.Header.Set("Origin", origin) - - resp, err := http.DefaultClient.Do(req) - if err != nil { - t.Fatal(err) - } - header := resp.Header.Get("Access-Control-Allow-Origin") - if header != origin { - t.Errorf("got Access-Control-Allow-Origin header %q, want %q", header, origin) - } - }) - - t.Run("preflight", func(t *testing.T) { - req, err := http.NewRequest(http.MethodOptions, url, nil) - if err != nil { - t.Fatal(err) - } - req.Header.Set("Origin", origin) - req.Header.Set("Access-Control-Request-Method", "GET") - - resp, err := http.DefaultClient.Do(req) - if err != nil { - t.Fatal(err) - } - header := resp.Header.Get("Access-Control-Allow-Origin") - if header != origin { - t.Errorf("got Access-Control-Allow-Origin header %q, want %q", header, origin) - } - }) -} - -// testStatusResponse makes an http request to provided url -// and validates if response is explorer.StatusResponse for -// the expected status code. -func testStatusResponse(t *testing.T, url string, code int) { - t.Helper() - - resp, err := http.Get(url) - if err != nil { - t.Fatal(err) - } - if resp.StatusCode != code { - t.Errorf("got status code %v, want %v", resp.StatusCode, code) - } - var r explorer.StatusResponse - if err := json.NewDecoder(resp.Body).Decode(&r); err != nil { - t.Fatal(err) - } - if r.Code != code { - t.Errorf("got response code %v, want %v", r.Code, code) - } - if r.Message != http.StatusText(code) { - t.Errorf("got response message %q, want %q", r.Message, http.StatusText(code)) - } -} - -// testKeysResponse makes an http request to provided url -// and validates if response machhes expected explorer.KeysResponse. -func testKeysResponse(t *testing.T, url string, want explorer.KeysResponse) { - t.Helper() - - resp, err := http.Get(url) - if err != nil { - t.Fatal(err) - } - if resp.StatusCode != http.StatusOK { - t.Errorf("got status code %v, want %v", resp.StatusCode, http.StatusOK) - } - var r explorer.KeysResponse - if err := json.NewDecoder(resp.Body).Decode(&r); err != nil { - t.Fatal(err) - } - if fmt.Sprint(r.Keys) != fmt.Sprint(want.Keys) { - t.Errorf("got keys %v, want %v", r.Keys, want.Keys) - } - if r.Next != want.Next { - t.Errorf("got next %s, want %s", r.Next, want.Next) - } -} - -// testNodeResponse makes an http request to provided url -// and validates if response machhes expected explorer.NodeResponse. -func testNodesResponse(t *testing.T, url string, want explorer.NodesResponse) { - t.Helper() - - resp, err := http.Get(url) - if err != nil { - t.Fatal(err) - } - if resp.StatusCode != http.StatusOK { - t.Errorf("got status code %v, want %v", resp.StatusCode, http.StatusOK) - } - var r explorer.NodesResponse - if err := json.NewDecoder(resp.Body).Decode(&r); err != nil { - t.Fatal(err) - } - if fmt.Sprint(r.Nodes) != fmt.Sprint(want.Nodes) { - t.Errorf("got nodes %v, want %v", r.Nodes, want.Nodes) - } - if r.Next != want.Next { - t.Errorf("got next %s, want %s", r.Next, want.Next) - } -} diff --git a/cmd/swarm/global-store/global_store.go b/cmd/swarm/global-store/global_store.go deleted file mode 100644 index f93b464db..000000000 --- a/cmd/swarm/global-store/global_store.go +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// go-ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. - -package main - -import ( - "io" - "net" - "net/http" - "os" - - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rpc" - "github.com/ethereum/go-ethereum/swarm/storage/mock" - "github.com/ethereum/go-ethereum/swarm/storage/mock/db" - "github.com/ethereum/go-ethereum/swarm/storage/mock/mem" - cli "gopkg.in/urfave/cli.v1" -) - -// startHTTP starts a global store with HTTP RPC server. -// It is used for "http" cli command. -func startHTTP(ctx *cli.Context) (err error) { - server, cleanup, err := newServer(ctx) - if err != nil { - return err - } - defer cleanup() - - listener, err := net.Listen("tcp", ctx.String("addr")) - if err != nil { - return err - } - log.Info("http", "address", listener.Addr().String()) - - return http.Serve(listener, server) -} - -// startWS starts a global store with WebSocket RPC server. -// It is used for "websocket" cli command. -func startWS(ctx *cli.Context) (err error) { - server, cleanup, err := newServer(ctx) - if err != nil { - return err - } - defer cleanup() - - listener, err := net.Listen("tcp", ctx.String("addr")) - if err != nil { - return err - } - origins := ctx.StringSlice("origins") - log.Info("websocket", "address", listener.Addr().String(), "origins", origins) - - return http.Serve(listener, server.WebsocketHandler(origins)) -} - -// newServer creates a global store and starts a chunk explorer server if configured. -// Returned cleanup function should be called only if err is nil. -func newServer(ctx *cli.Context) (server *rpc.Server, cleanup func(), err error) { - log.PrintOrigins(true) - log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(ctx.Int("verbosity")), log.StreamHandler(os.Stdout, log.TerminalFormat(false)))) - - cleanup = func() {} - var globalStore mock.GlobalStorer - dir := ctx.String("dir") - if dir != "" { - dbStore, err := db.NewGlobalStore(dir) - if err != nil { - return nil, nil, err - } - cleanup = func() { - if err := dbStore.Close(); err != nil { - log.Error("global store: close", "err", err) - } - } - globalStore = dbStore - log.Info("database global store", "dir", dir) - } else { - globalStore = mem.NewGlobalStore() - log.Info("in-memory global store") - } - - server = rpc.NewServer() - if err := server.RegisterName("mockStore", globalStore); err != nil { - cleanup() - return nil, nil, err - } - - shutdown, err := serveChunkExplorer(ctx, globalStore) - if err != nil { - cleanup() - return nil, nil, err - } - if shutdown != nil { - cleanup = func() { - shutdown() - - if c, ok := globalStore.(io.Closer); ok { - if err := c.Close(); err != nil { - log.Error("global store: close", "err", err) - } - } - } - } - - return server, cleanup, nil -} diff --git a/cmd/swarm/global-store/global_store_test.go b/cmd/swarm/global-store/global_store_test.go deleted file mode 100644 index c437c9d45..000000000 --- a/cmd/swarm/global-store/global_store_test.go +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// go-ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. - -package main - -import ( - "context" - "io/ioutil" - "net" - "net/http" - "os" - "testing" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/rpc" - mockRPC "github.com/ethereum/go-ethereum/swarm/storage/mock/rpc" -) - -// TestHTTP_InMemory tests in-memory global store that exposes -// HTTP server. -func TestHTTP_InMemory(t *testing.T) { - testHTTP(t, true) -} - -// TestHTTP_Database tests global store with persisted database -// that exposes HTTP server. -func TestHTTP_Database(t *testing.T) { - dir, err := ioutil.TempDir("", "swarm-global-store-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dir) - - // create a fresh global store - testHTTP(t, true, "--dir", dir) - - // check if data saved by the previous global store instance - testHTTP(t, false, "--dir", dir) -} - -// testWebsocket starts global store binary with HTTP server -// and validates that it can store and retrieve data. -// If put is false, no data will be stored, only retrieved, -// giving the possibility to check if data is present in the -// storage directory. -func testHTTP(t *testing.T, put bool, args ...string) { - addr := findFreeTCPAddress(t) - testCmd := runGlobalStore(t, append([]string{"http", "--addr", addr}, args...)...) - defer testCmd.Kill() - - client, err := rpc.DialHTTP("http://" + addr) - if err != nil { - t.Fatal(err) - } - - // wait until global store process is started as - // rpc.DialHTTP is actually not connecting - waitHTTPEndpoint(t, addr) - - store := mockRPC.NewGlobalStore(client) - defer store.Close() - - node := store.NewNodeStore(common.HexToAddress("123abc")) - - wantKey := "key" - wantValue := "value" - - if put { - err = node.Put([]byte(wantKey), []byte(wantValue)) - if err != nil { - t.Fatal(err) - } - } - - gotValue, err := node.Get([]byte(wantKey)) - if err != nil { - t.Fatal(err) - } - - if string(gotValue) != wantValue { - t.Errorf("got value %s for key %s, want %s", string(gotValue), wantKey, wantValue) - } -} - -// TestWebsocket_InMemory tests in-memory global store that exposes -// WebSocket server. -func TestWebsocket_InMemory(t *testing.T) { - testWebsocket(t, true) -} - -// TestWebsocket_Database tests global store with persisted database -// that exposes HTTP server. -func TestWebsocket_Database(t *testing.T) { - dir, err := ioutil.TempDir("", "swarm-global-store-") - if err != nil { - t.Fatal(err) - } - defer os.RemoveAll(dir) - - // create a fresh global store - testWebsocket(t, true, "--dir", dir) - - // check if data saved by the previous global store instance - testWebsocket(t, false, "--dir", dir) -} - -// testWebsocket starts global store binary with WebSocket server -// and validates that it can store and retrieve data. -// If put is false, no data will be stored, only retrieved, -// giving the possibility to check if data is present in the -// storage directory. -func testWebsocket(t *testing.T, put bool, args ...string) { - addr := findFreeTCPAddress(t) - testCmd := runGlobalStore(t, append([]string{"ws", "--addr", addr}, args...)...) - defer testCmd.Kill() - - client := websocketClient(t, addr) - - store := mockRPC.NewGlobalStore(client) - defer store.Close() - - node := store.NewNodeStore(common.HexToAddress("123abc")) - - wantKey := "key" - wantValue := "value" - - if put { - err := node.Put([]byte(wantKey), []byte(wantValue)) - if err != nil { - t.Fatal(err) - } - } - - gotValue, err := node.Get([]byte(wantKey)) - if err != nil { - t.Fatal(err) - } - - if string(gotValue) != wantValue { - t.Errorf("got value %s for key %s, want %s", string(gotValue), wantKey, wantValue) - } -} - -// findFreeTCPAddress returns a local address (IP:Port) to which -// global store can listen on. -func findFreeTCPAddress(t *testing.T) (addr string) { - t.Helper() - - listener, err := net.Listen("tcp", "") - if err != nil { - t.Fatal(err) - } - defer listener.Close() - - return listener.Addr().String() -} - -// websocketClient waits until global store process is started -// and returns rpc client. -func websocketClient(t *testing.T, addr string) (client *rpc.Client) { - t.Helper() - - var err error - for i := 0; i < 1000; i++ { - client, err = rpc.DialWebsocket(context.Background(), "ws://"+addr, "") - if err == nil { - break - } - time.Sleep(10 * time.Millisecond) - } - if err != nil { - t.Fatal(err) - } - return client -} - -// waitHTTPEndpoint retries http requests to a provided -// address until the connection is established. -func waitHTTPEndpoint(t *testing.T, addr string) { - t.Helper() - - var err error - for i := 0; i < 1000; i++ { - _, err = http.Get("http://" + addr) - if err == nil { - break - } - time.Sleep(10 * time.Millisecond) - } - if err != nil { - t.Fatal(err) - } -} diff --git a/cmd/swarm/global-store/main.go b/cmd/swarm/global-store/main.go deleted file mode 100644 index 58505f988..000000000 --- a/cmd/swarm/global-store/main.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// go-ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. - -package main - -import ( - "os" - - "github.com/ethereum/go-ethereum/log" - cli "gopkg.in/urfave/cli.v1" -) - -var ( - version = "0.1" - gitCommit string // Git SHA1 commit hash of the release (set via linker flags) - gitDate string -) - -func main() { - err := newApp().Run(os.Args) - if err != nil { - log.Error(err.Error()) - os.Exit(1) - } -} - -// newApp construct a new instance of Swarm Global Store. -// Method Run is called on it in the main function and in tests. -func newApp() (app *cli.App) { - app = cli.NewApp() - app.Name = "global-store" - app.Version = version - if len(gitCommit) >= 8 { - app.Version += "-" + gitCommit[:8] - } - if gitDate != "" { - app.Version += "-" + gitDate - } - app.Usage = "Swarm Global Store" - - // app flags (for all commands) - app.Flags = []cli.Flag{ - cli.IntFlag{ - Name: "verbosity", - Value: 3, - Usage: "Verbosity level.", - }, - cli.StringFlag{ - Name: "explorer-address", - Value: "", - Usage: "Chunk explorer HTTP listener address.", - }, - cli.StringSliceFlag{ - Name: "explorer-cors-origin", - Value: nil, - Usage: "Chunk explorer CORS origin (can be specified multiple times).", - }, - } - - app.Commands = []cli.Command{ - { - Name: "http", - Aliases: []string{"h"}, - Usage: "Start swarm global store with HTTP server.", - Action: startHTTP, - // Flags only for "start" command. - // Allow app flags to be specified after the - // command argument. - Flags: append(app.Flags, - cli.StringFlag{ - Name: "dir", - Value: "", - Usage: "Data directory.", - }, - cli.StringFlag{ - Name: "addr", - Value: "0.0.0.0:3033", - Usage: "Address to listen for HTTP connections.", - }, - ), - }, - { - Name: "websocket", - Aliases: []string{"ws"}, - Usage: "Start swarm global store with WebSocket server.", - Action: startWS, - // Flags only for "start" command. - // Allow app flags to be specified after the - // command argument. - Flags: append(app.Flags, - cli.StringFlag{ - Name: "dir", - Value: "", - Usage: "Data directory.", - }, - cli.StringFlag{ - Name: "addr", - Value: "0.0.0.0:3033", - Usage: "Address to listen for WebSocket connections.", - }, - cli.StringSliceFlag{ - Name: "origin", - Value: nil, - Usage: "WebSocket CORS origin (can be specified multiple times).", - }, - ), - }, - } - - return app -} diff --git a/cmd/swarm/global-store/run_test.go b/cmd/swarm/global-store/run_test.go deleted file mode 100644 index d7ef626e5..000000000 --- a/cmd/swarm/global-store/run_test.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2019 The go-ethereum Authors -// This file is part of go-ethereum. -// -// go-ethereum is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// go-ethereum is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. - -package main - -import ( - "fmt" - "os" - "testing" - - "github.com/docker/docker/pkg/reexec" - "github.com/ethereum/go-ethereum/internal/cmdtest" -) - -func init() { - reexec.Register("swarm-global-store", func() { - if err := newApp().Run(os.Args); err != nil { - fmt.Fprintln(os.Stderr, err) - os.Exit(1) - } - os.Exit(0) - }) -} - -func runGlobalStore(t *testing.T, args ...string) *cmdtest.TestCmd { - tt := cmdtest.NewTestCmd(t, nil) - tt.Run("swarm-global-store", args...) - return tt -} - -func TestMain(m *testing.M) { - if reexec.Init() { - return - } - os.Exit(m.Run()) -} |