github.com/SmartMeshFoundation/Spectrum@v0.0.0-20220621030607-452a266fee1e/swarm/api/api_test.go (about)

     1  // Copyright 2016 The Spectrum Authors
     2  // This file is part of the Spectrum library.
     3  //
     4  // The Spectrum 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 Spectrum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY 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 Spectrum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package api
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"io"
    23  	"io/ioutil"
    24  	"os"
    25  	"testing"
    26  
    27  	"github.com/SmartMeshFoundation/Spectrum/common"
    28  	"github.com/SmartMeshFoundation/Spectrum/log"
    29  	"github.com/SmartMeshFoundation/Spectrum/swarm/storage"
    30  )
    31  
    32  func testApi(t *testing.T, f func(*Api)) {
    33  	datadir, err := ioutil.TempDir("", "bzz-test")
    34  	if err != nil {
    35  		t.Fatalf("unable to create temp dir: %v", err)
    36  	}
    37  	os.RemoveAll(datadir)
    38  	defer os.RemoveAll(datadir)
    39  	dpa, err := storage.NewLocalDPA(datadir)
    40  	if err != nil {
    41  		return
    42  	}
    43  	api := NewApi(dpa, nil)
    44  	dpa.Start()
    45  	f(api)
    46  	dpa.Stop()
    47  }
    48  
    49  type testResponse struct {
    50  	reader storage.LazySectionReader
    51  	*Response
    52  }
    53  
    54  func checkResponse(t *testing.T, resp *testResponse, exp *Response) {
    55  
    56  	if resp.MimeType != exp.MimeType {
    57  		t.Errorf("incorrect mimeType. expected '%s', got '%s'", exp.MimeType, resp.MimeType)
    58  	}
    59  	if resp.Status != exp.Status {
    60  		t.Errorf("incorrect status. expected '%d', got '%d'", exp.Status, resp.Status)
    61  	}
    62  	if resp.Size != exp.Size {
    63  		t.Errorf("incorrect size. expected '%d', got '%d'", exp.Size, resp.Size)
    64  	}
    65  	if resp.reader != nil {
    66  		content := make([]byte, resp.Size)
    67  		read, _ := resp.reader.Read(content)
    68  		if int64(read) != exp.Size {
    69  			t.Errorf("incorrect content length. expected '%d...', got '%d...'", read, exp.Size)
    70  		}
    71  		resp.Content = string(content)
    72  	}
    73  	if resp.Content != exp.Content {
    74  		// if !bytes.Equal(resp.Content, exp.Content)
    75  		t.Errorf("incorrect content. expected '%s...', got '%s...'", string(exp.Content), string(resp.Content))
    76  	}
    77  }
    78  
    79  // func expResponse(content []byte, mimeType string, status int) *Response {
    80  func expResponse(content string, mimeType string, status int) *Response {
    81  	log.Trace(fmt.Sprintf("expected content (%v): %v ", len(content), content))
    82  	return &Response{mimeType, status, int64(len(content)), content}
    83  }
    84  
    85  // func testGet(t *testing.T, api *Api, bzzhash string) *testResponse {
    86  func testGet(t *testing.T, api *Api, bzzhash, path string) *testResponse {
    87  	key := storage.Key(common.Hex2Bytes(bzzhash))
    88  	reader, mimeType, status, err := api.Get(key, path)
    89  	if err != nil {
    90  		t.Fatalf("unexpected error: %v", err)
    91  	}
    92  	quitC := make(chan bool)
    93  	size, err := reader.Size(quitC)
    94  	if err != nil {
    95  		t.Fatalf("unexpected error: %v", err)
    96  	}
    97  	log.Trace(fmt.Sprintf("reader size: %v ", size))
    98  	s := make([]byte, size)
    99  	_, err = reader.Read(s)
   100  	if err != io.EOF {
   101  		t.Fatalf("unexpected error: %v", err)
   102  	}
   103  	reader.Seek(0, 0)
   104  	return &testResponse{reader, &Response{mimeType, status, size, string(s)}}
   105  	// return &testResponse{reader, &Response{mimeType, status, reader.Size(), nil}}
   106  }
   107  
   108  func TestApiPut(t *testing.T) {
   109  	testApi(t, func(api *Api) {
   110  		content := "hello"
   111  		exp := expResponse(content, "text/plain", 0)
   112  		// exp := expResponse([]byte(content), "text/plain", 0)
   113  		key, err := api.Put(content, exp.MimeType)
   114  		if err != nil {
   115  			t.Fatalf("unexpected error: %v", err)
   116  		}
   117  		resp := testGet(t, api, key.String(), "")
   118  		checkResponse(t, resp, exp)
   119  	})
   120  }
   121  
   122  // testResolver implements the Resolver interface and either returns the given
   123  // hash if it is set, or returns a "name not found" error
   124  type testResolver struct {
   125  	hash *common.Hash
   126  }
   127  
   128  func newTestResolver(addr string) *testResolver {
   129  	r := &testResolver{}
   130  	if addr != "" {
   131  		hash := common.HexToHash(addr)
   132  		r.hash = &hash
   133  	}
   134  	return r
   135  }
   136  
   137  func (t *testResolver) Resolve(addr string) (common.Hash, error) {
   138  	if t.hash == nil {
   139  		return common.Hash{}, fmt.Errorf("DNS name not found: %q", addr)
   140  	}
   141  	return *t.hash, nil
   142  }
   143  
   144  // TestAPIResolve tests resolving URIs which can either contain content hashes
   145  // or ENS names
   146  func TestAPIResolve(t *testing.T) {
   147  	ensAddr := "swarm.eth"
   148  	hashAddr := "1111111111111111111111111111111111111111111111111111111111111111"
   149  	resolvedAddr := "2222222222222222222222222222222222222222222222222222222222222222"
   150  	doesResolve := newTestResolver(resolvedAddr)
   151  	doesntResolve := newTestResolver("")
   152  
   153  	type test struct {
   154  		desc      string
   155  		dns       Resolver
   156  		addr      string
   157  		immutable bool
   158  		result    string
   159  		expectErr error
   160  	}
   161  
   162  	tests := []*test{
   163  		{
   164  			desc:   "DNS not configured, hash address, returns hash address",
   165  			dns:    nil,
   166  			addr:   hashAddr,
   167  			result: hashAddr,
   168  		},
   169  		{
   170  			desc:      "DNS not configured, ENS address, returns error",
   171  			dns:       nil,
   172  			addr:      ensAddr,
   173  			expectErr: errors.New(`no DNS to resolve name: "swarm.eth"`),
   174  		},
   175  		{
   176  			desc:   "DNS configured, hash address, hash resolves, returns resolved address",
   177  			dns:    doesResolve,
   178  			addr:   hashAddr,
   179  			result: resolvedAddr,
   180  		},
   181  		{
   182  			desc:      "DNS configured, immutable hash address, hash resolves, returns hash address",
   183  			dns:       doesResolve,
   184  			addr:      hashAddr,
   185  			immutable: true,
   186  			result:    hashAddr,
   187  		},
   188  		{
   189  			desc:   "DNS configured, hash address, hash doesn't resolve, returns hash address",
   190  			dns:    doesntResolve,
   191  			addr:   hashAddr,
   192  			result: hashAddr,
   193  		},
   194  		{
   195  			desc:   "DNS configured, ENS address, name resolves, returns resolved address",
   196  			dns:    doesResolve,
   197  			addr:   ensAddr,
   198  			result: resolvedAddr,
   199  		},
   200  		{
   201  			desc:      "DNS configured, immutable ENS address, name resolves, returns error",
   202  			dns:       doesResolve,
   203  			addr:      ensAddr,
   204  			immutable: true,
   205  			expectErr: errors.New(`immutable address not a content hash: "swarm.eth"`),
   206  		},
   207  		{
   208  			desc:      "DNS configured, ENS address, name doesn't resolve, returns error",
   209  			dns:       doesntResolve,
   210  			addr:      ensAddr,
   211  			expectErr: errors.New(`DNS name not found: "swarm.eth"`),
   212  		},
   213  	}
   214  	for _, x := range tests {
   215  		t.Run(x.desc, func(t *testing.T) {
   216  			api := &Api{dns: x.dns}
   217  			uri := &URI{Addr: x.addr, Scheme: "bzz"}
   218  			if x.immutable {
   219  				uri.Scheme = "bzz-immutable"
   220  			}
   221  			res, err := api.Resolve(uri)
   222  			if err == nil {
   223  				if x.expectErr != nil {
   224  					t.Fatalf("expected error %q, got result %q", x.expectErr, res)
   225  				}
   226  				if res.String() != x.result {
   227  					t.Fatalf("expected result %q, got %q", x.result, res)
   228  				}
   229  			} else {
   230  				if x.expectErr == nil {
   231  					t.Fatalf("expected no error, got %q", err)
   232  				}
   233  				if err.Error() != x.expectErr.Error() {
   234  					t.Fatalf("expected error %q, got %q", x.expectErr, err)
   235  				}
   236  			}
   237  		})
   238  	}
   239  }