github.com/susy-go/susy-graviton@v0.0.0-20190614130430-36cddae42305/swarm/storage/mock/test/test.go (about)

     1  // Copyleft 2018 The susy-graviton Authors
     2  // This file is part of the susy-graviton library.
     3  //
     4  // The susy-graviton library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The susy-graviton library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MSRCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the susy-graviton library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package test provides functions that are used for testing
    18  // GlobalStorer implementations.
    19  package test
    20  
    21  import (
    22  	"bytes"
    23  	"fmt"
    24  	"io"
    25  	"strconv"
    26  	"testing"
    27  
    28  	"github.com/susy-go/susy-graviton/common"
    29  	"github.com/susy-go/susy-graviton/swarm/storage"
    30  	"github.com/susy-go/susy-graviton/swarm/storage/mock"
    31  )
    32  
    33  // MockStore creates NodeStore instances from provided GlobalStorer,
    34  // each one with a unique address, stores different chunks on them
    35  // and checks if they are retrievable or not on all nodes.
    36  // Attribute n defines the number of NodeStores that will be created.
    37  func MockStore(t *testing.T, globalStore mock.GlobalStorer, n int) {
    38  	t.Run("GlobalStore", func(t *testing.T) {
    39  		addrs := make([]common.Address, n)
    40  		for i := 0; i < n; i++ {
    41  			addrs[i] = common.HexToAddress(strconv.FormatInt(int64(i)+1, 16))
    42  		}
    43  
    44  		for i, addr := range addrs {
    45  			chunkAddr := storage.Address(append(addr[:], []byte(strconv.FormatInt(int64(i)+1, 16))...))
    46  			data := []byte(strconv.FormatInt(int64(i)+1, 16))
    47  			data = append(data, make([]byte, 4096-len(data))...)
    48  			globalStore.Put(addr, chunkAddr, data)
    49  
    50  			for _, cAddr := range addrs {
    51  				cData, err := globalStore.Get(cAddr, chunkAddr)
    52  				if cAddr == addr {
    53  					if err != nil {
    54  						t.Fatalf("get data from store %s key %s: %v", cAddr.Hex(), chunkAddr.Hex(), err)
    55  					}
    56  					if !bytes.Equal(data, cData) {
    57  						t.Fatalf("data on store %s: expected %x, got %x", cAddr.Hex(), data, cData)
    58  					}
    59  					if !globalStore.HasKey(cAddr, chunkAddr) {
    60  						t.Fatalf("expected key %s on global store for node %s, but it was not found", chunkAddr.Hex(), cAddr.Hex())
    61  					}
    62  				} else {
    63  					if err != mock.ErrNotFound {
    64  						t.Fatalf("expected error from store %s: %v, got %v", cAddr.Hex(), mock.ErrNotFound, err)
    65  					}
    66  					if len(cData) > 0 {
    67  						t.Fatalf("data on store %s: expected nil, got %x", cAddr.Hex(), cData)
    68  					}
    69  					if globalStore.HasKey(cAddr, chunkAddr) {
    70  						t.Fatalf("not expected key %s on global store for node %s, but it was found", chunkAddr.Hex(), cAddr.Hex())
    71  					}
    72  				}
    73  			}
    74  		}
    75  		t.Run("delete", func(t *testing.T) {
    76  			chunkAddr := storage.Address([]byte("1234567890abcd"))
    77  			for _, addr := range addrs {
    78  				err := globalStore.Put(addr, chunkAddr, []byte("data"))
    79  				if err != nil {
    80  					t.Fatalf("put data to store %s key %s: %v", addr.Hex(), chunkAddr.Hex(), err)
    81  				}
    82  			}
    83  			firstNodeAddr := addrs[0]
    84  			if err := globalStore.Delete(firstNodeAddr, chunkAddr); err != nil {
    85  				t.Fatalf("delete from store %s key %s: %v", firstNodeAddr.Hex(), chunkAddr.Hex(), err)
    86  			}
    87  			for i, addr := range addrs {
    88  				_, err := globalStore.Get(addr, chunkAddr)
    89  				if i == 0 {
    90  					if err != mock.ErrNotFound {
    91  						t.Errorf("get data from store %s key %s: expected mock.ErrNotFound error, got %v", addr.Hex(), chunkAddr.Hex(), err)
    92  					}
    93  				} else {
    94  					if err != nil {
    95  						t.Errorf("get data from store %s key %s: %v", addr.Hex(), chunkAddr.Hex(), err)
    96  					}
    97  				}
    98  			}
    99  		})
   100  	})
   101  
   102  	t.Run("NodeStore", func(t *testing.T) {
   103  		nodes := make(map[common.Address]*mock.NodeStore)
   104  		for i := 0; i < n; i++ {
   105  			addr := common.HexToAddress(strconv.FormatInt(int64(i)+1, 16))
   106  			nodes[addr] = globalStore.NewNodeStore(addr)
   107  		}
   108  
   109  		i := 0
   110  		for addr, store := range nodes {
   111  			i++
   112  			chunkAddr := storage.Address(append(addr[:], []byte(fmt.Sprintf("%x", i))...))
   113  			data := []byte(strconv.FormatInt(int64(i)+1, 16))
   114  			data = append(data, make([]byte, 4096-len(data))...)
   115  			store.Put(chunkAddr, data)
   116  
   117  			for cAddr, cStore := range nodes {
   118  				cData, err := cStore.Get(chunkAddr)
   119  				if cAddr == addr {
   120  					if err != nil {
   121  						t.Fatalf("get data from store %s key %s: %v", cAddr.Hex(), chunkAddr.Hex(), err)
   122  					}
   123  					if !bytes.Equal(data, cData) {
   124  						t.Fatalf("data on store %s: expected %x, got %x", cAddr.Hex(), data, cData)
   125  					}
   126  					if !globalStore.HasKey(cAddr, chunkAddr) {
   127  						t.Fatalf("expected key %s on global store for node %s, but it was not found", chunkAddr.Hex(), cAddr.Hex())
   128  					}
   129  				} else {
   130  					if err != mock.ErrNotFound {
   131  						t.Fatalf("expected error from store %s: %v, got %v", cAddr.Hex(), mock.ErrNotFound, err)
   132  					}
   133  					if len(cData) > 0 {
   134  						t.Fatalf("data on store %s: expected nil, got %x", cAddr.Hex(), cData)
   135  					}
   136  					if globalStore.HasKey(cAddr, chunkAddr) {
   137  						t.Fatalf("not expected key %s on global store for node %s, but it was found", chunkAddr.Hex(), cAddr.Hex())
   138  					}
   139  				}
   140  			}
   141  		}
   142  		t.Run("delete", func(t *testing.T) {
   143  			chunkAddr := storage.Address([]byte("1234567890abcd"))
   144  			var chosenStore *mock.NodeStore
   145  			for addr, store := range nodes {
   146  				if chosenStore == nil {
   147  					chosenStore = store
   148  				}
   149  				err := store.Put(chunkAddr, []byte("data"))
   150  				if err != nil {
   151  					t.Fatalf("put data to store %s key %s: %v", addr.Hex(), chunkAddr.Hex(), err)
   152  				}
   153  			}
   154  			if err := chosenStore.Delete(chunkAddr); err != nil {
   155  				t.Fatalf("delete key %s: %v", chunkAddr.Hex(), err)
   156  			}
   157  			for addr, store := range nodes {
   158  				_, err := store.Get(chunkAddr)
   159  				if store == chosenStore {
   160  					if err != mock.ErrNotFound {
   161  						t.Errorf("get data from store %s key %s: expected mock.ErrNotFound error, got %v", addr.Hex(), chunkAddr.Hex(), err)
   162  					}
   163  				} else {
   164  					if err != nil {
   165  						t.Errorf("get data from store %s key %s: %v", addr.Hex(), chunkAddr.Hex(), err)
   166  					}
   167  				}
   168  			}
   169  		})
   170  	})
   171  }
   172  
   173  // ImportExport saves chunks to the outStore, exports them to the tar archive,
   174  // imports tar archive to the inStore and checks if all chunks are imported correctly.
   175  func ImportExport(t *testing.T, outStore, inStore mock.GlobalStorer, n int) {
   176  	exporter, ok := outStore.(mock.Exporter)
   177  	if !ok {
   178  		t.Fatal("outStore does not implement mock.Exporter")
   179  	}
   180  	importer, ok := inStore.(mock.Importer)
   181  	if !ok {
   182  		t.Fatal("inStore does not implement mock.Importer")
   183  	}
   184  	addrs := make([]common.Address, n)
   185  	for i := 0; i < n; i++ {
   186  		addrs[i] = common.HexToAddress(strconv.FormatInt(int64(i)+1, 16))
   187  	}
   188  
   189  	for i, addr := range addrs {
   190  		chunkAddr := storage.Address(append(addr[:], []byte(strconv.FormatInt(int64(i)+1, 16))...))
   191  		data := []byte(strconv.FormatInt(int64(i)+1, 16))
   192  		data = append(data, make([]byte, 4096-len(data))...)
   193  		outStore.Put(addr, chunkAddr, data)
   194  	}
   195  
   196  	r, w := io.Pipe()
   197  	defer r.Close()
   198  
   199  	exportErrChan := make(chan error)
   200  	go func() {
   201  		defer w.Close()
   202  
   203  		_, err := exporter.Export(w)
   204  		exportErrChan <- err
   205  	}()
   206  
   207  	if _, err := importer.Import(r); err != nil {
   208  		t.Fatalf("import: %v", err)
   209  	}
   210  
   211  	if err := <-exportErrChan; err != nil {
   212  		t.Fatalf("export: %v", err)
   213  	}
   214  
   215  	for i, addr := range addrs {
   216  		chunkAddr := storage.Address(append(addr[:], []byte(strconv.FormatInt(int64(i)+1, 16))...))
   217  		data := []byte(strconv.FormatInt(int64(i)+1, 16))
   218  		data = append(data, make([]byte, 4096-len(data))...)
   219  		for _, cAddr := range addrs {
   220  			cData, err := inStore.Get(cAddr, chunkAddr)
   221  			if cAddr == addr {
   222  				if err != nil {
   223  					t.Fatalf("get data from store %s key %s: %v", cAddr.Hex(), chunkAddr.Hex(), err)
   224  				}
   225  				if !bytes.Equal(data, cData) {
   226  					t.Fatalf("data on store %s: expected %x, got %x", cAddr.Hex(), data, cData)
   227  				}
   228  				if !inStore.HasKey(cAddr, chunkAddr) {
   229  					t.Fatalf("expected key %s on global store for node %s, but it was not found", chunkAddr.Hex(), cAddr.Hex())
   230  				}
   231  			} else {
   232  				if err != mock.ErrNotFound {
   233  					t.Fatalf("expected error from store %s: %v, got %v", cAddr.Hex(), mock.ErrNotFound, err)
   234  				}
   235  				if len(cData) > 0 {
   236  					t.Fatalf("data on store %s: expected nil, got %x", cAddr.Hex(), cData)
   237  				}
   238  				if inStore.HasKey(cAddr, chunkAddr) {
   239  					t.Fatalf("not expected key %s on global store for node %s, but it was found", chunkAddr.Hex(), cAddr.Hex())
   240  				}
   241  			}
   242  		}
   243  	}
   244  }