github.com/gobitfly/go-ethereum@v1.8.12/swarm/api/api_test.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum 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 go-ethereum 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 go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package api
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"fmt"
    23  	"io"
    24  	"io/ioutil"
    25  	"math/big"
    26  	"os"
    27  	"testing"
    28  
    29  	"github.com/ethereum/go-ethereum/common"
    30  	"github.com/ethereum/go-ethereum/core/types"
    31  	"github.com/ethereum/go-ethereum/swarm/log"
    32  	"github.com/ethereum/go-ethereum/swarm/storage"
    33  )
    34  
    35  func testAPI(t *testing.T, f func(*API, bool)) {
    36  	datadir, err := ioutil.TempDir("", "bzz-test")
    37  	if err != nil {
    38  		t.Fatalf("unable to create temp dir: %v", err)
    39  	}
    40  	defer os.RemoveAll(datadir)
    41  	fileStore, err := storage.NewLocalFileStore(datadir, make([]byte, 32))
    42  	if err != nil {
    43  		return
    44  	}
    45  	api := NewAPI(fileStore, nil, nil)
    46  	f(api, false)
    47  	f(api, true)
    48  }
    49  
    50  type testResponse struct {
    51  	reader storage.LazySectionReader
    52  	*Response
    53  }
    54  
    55  func checkResponse(t *testing.T, resp *testResponse, exp *Response) {
    56  
    57  	if resp.MimeType != exp.MimeType {
    58  		t.Errorf("incorrect mimeType. expected '%s', got '%s'", exp.MimeType, resp.MimeType)
    59  	}
    60  	if resp.Status != exp.Status {
    61  		t.Errorf("incorrect status. expected '%d', got '%d'", exp.Status, resp.Status)
    62  	}
    63  	if resp.Size != exp.Size {
    64  		t.Errorf("incorrect size. expected '%d', got '%d'", exp.Size, resp.Size)
    65  	}
    66  	if resp.reader != nil {
    67  		content := make([]byte, resp.Size)
    68  		read, _ := resp.reader.Read(content)
    69  		if int64(read) != exp.Size {
    70  			t.Errorf("incorrect content length. expected '%d...', got '%d...'", read, exp.Size)
    71  		}
    72  		resp.Content = string(content)
    73  	}
    74  	if resp.Content != exp.Content {
    75  		// if !bytes.Equal(resp.Content, exp.Content)
    76  		t.Errorf("incorrect content. expected '%s...', got '%s...'", string(exp.Content), string(resp.Content))
    77  	}
    78  }
    79  
    80  // func expResponse(content []byte, mimeType string, status int) *Response {
    81  func expResponse(content string, mimeType string, status int) *Response {
    82  	log.Trace(fmt.Sprintf("expected content (%v): %v ", len(content), content))
    83  	return &Response{mimeType, status, int64(len(content)), content}
    84  }
    85  
    86  func testGet(t *testing.T, api *API, bzzhash, path string) *testResponse {
    87  	addr := storage.Address(common.Hex2Bytes(bzzhash))
    88  	reader, mimeType, status, _, err := api.Get(addr, 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, toEncrypt bool) {
   110  		content := "hello"
   111  		exp := expResponse(content, "text/plain", 0)
   112  		// exp := expResponse([]byte(content), "text/plain", 0)
   113  		addr, wait, err := api.Put(content, exp.MimeType, toEncrypt)
   114  		if err != nil {
   115  			t.Fatalf("unexpected error: %v", err)
   116  		}
   117  		wait()
   118  		resp := testGet(t, api, addr.Hex(), "")
   119  		checkResponse(t, resp, exp)
   120  	})
   121  }
   122  
   123  // testResolver implements the Resolver interface and either returns the given
   124  // hash if it is set, or returns a "name not found" error
   125  type testResolveValidator struct {
   126  	hash *common.Hash
   127  }
   128  
   129  func newTestResolveValidator(addr string) *testResolveValidator {
   130  	r := &testResolveValidator{}
   131  	if addr != "" {
   132  		hash := common.HexToHash(addr)
   133  		r.hash = &hash
   134  	}
   135  	return r
   136  }
   137  
   138  func (t *testResolveValidator) Resolve(addr string) (common.Hash, error) {
   139  	if t.hash == nil {
   140  		return common.Hash{}, fmt.Errorf("DNS name not found: %q", addr)
   141  	}
   142  	return *t.hash, nil
   143  }
   144  
   145  func (t *testResolveValidator) Owner(node [32]byte) (addr common.Address, err error) {
   146  	return
   147  }
   148  func (t *testResolveValidator) HeaderByNumber(context.Context, *big.Int) (header *types.Header, err error) {
   149  	return
   150  }
   151  
   152  // TestAPIResolve tests resolving URIs which can either contain content hashes
   153  // or ENS names
   154  func TestAPIResolve(t *testing.T) {
   155  	ensAddr := "swarm.eth"
   156  	hashAddr := "1111111111111111111111111111111111111111111111111111111111111111"
   157  	resolvedAddr := "2222222222222222222222222222222222222222222222222222222222222222"
   158  	doesResolve := newTestResolveValidator(resolvedAddr)
   159  	doesntResolve := newTestResolveValidator("")
   160  
   161  	type test struct {
   162  		desc      string
   163  		dns       Resolver
   164  		addr      string
   165  		immutable bool
   166  		result    string
   167  		expectErr error
   168  	}
   169  
   170  	tests := []*test{
   171  		{
   172  			desc:   "DNS not configured, hash address, returns hash address",
   173  			dns:    nil,
   174  			addr:   hashAddr,
   175  			result: hashAddr,
   176  		},
   177  		{
   178  			desc:      "DNS not configured, ENS address, returns error",
   179  			dns:       nil,
   180  			addr:      ensAddr,
   181  			expectErr: errors.New(`no DNS to resolve name: "swarm.eth"`),
   182  		},
   183  		{
   184  			desc:   "DNS configured, hash address, hash resolves, returns resolved address",
   185  			dns:    doesResolve,
   186  			addr:   hashAddr,
   187  			result: resolvedAddr,
   188  		},
   189  		{
   190  			desc:      "DNS configured, immutable hash address, hash resolves, returns hash address",
   191  			dns:       doesResolve,
   192  			addr:      hashAddr,
   193  			immutable: true,
   194  			result:    hashAddr,
   195  		},
   196  		{
   197  			desc:   "DNS configured, hash address, hash doesn't resolve, returns hash address",
   198  			dns:    doesntResolve,
   199  			addr:   hashAddr,
   200  			result: hashAddr,
   201  		},
   202  		{
   203  			desc:   "DNS configured, ENS address, name resolves, returns resolved address",
   204  			dns:    doesResolve,
   205  			addr:   ensAddr,
   206  			result: resolvedAddr,
   207  		},
   208  		{
   209  			desc:      "DNS configured, immutable ENS address, name resolves, returns error",
   210  			dns:       doesResolve,
   211  			addr:      ensAddr,
   212  			immutable: true,
   213  			expectErr: errors.New(`immutable address not a content hash: "swarm.eth"`),
   214  		},
   215  		{
   216  			desc:      "DNS configured, ENS address, name doesn't resolve, returns error",
   217  			dns:       doesntResolve,
   218  			addr:      ensAddr,
   219  			expectErr: errors.New(`DNS name not found: "swarm.eth"`),
   220  		},
   221  	}
   222  	for _, x := range tests {
   223  		t.Run(x.desc, func(t *testing.T) {
   224  			api := &API{dns: x.dns}
   225  			uri := &URI{Addr: x.addr, Scheme: "bzz"}
   226  			if x.immutable {
   227  				uri.Scheme = "bzz-immutable"
   228  			}
   229  			res, err := api.Resolve(uri)
   230  			if err == nil {
   231  				if x.expectErr != nil {
   232  					t.Fatalf("expected error %q, got result %q", x.expectErr, res)
   233  				}
   234  				if res.String() != x.result {
   235  					t.Fatalf("expected result %q, got %q", x.result, res)
   236  				}
   237  			} else {
   238  				if x.expectErr == nil {
   239  					t.Fatalf("expected no error, got %q", err)
   240  				}
   241  				if err.Error() != x.expectErr.Error() {
   242  					t.Fatalf("expected error %q, got %q", x.expectErr, err)
   243  				}
   244  			}
   245  		})
   246  	}
   247  }
   248  
   249  func TestMultiResolver(t *testing.T) {
   250  	doesntResolve := newTestResolveValidator("")
   251  
   252  	ethAddr := "swarm.eth"
   253  	ethHash := "0x2222222222222222222222222222222222222222222222222222222222222222"
   254  	ethResolve := newTestResolveValidator(ethHash)
   255  
   256  	testAddr := "swarm.test"
   257  	testHash := "0x1111111111111111111111111111111111111111111111111111111111111111"
   258  	testResolve := newTestResolveValidator(testHash)
   259  
   260  	tests := []struct {
   261  		desc   string
   262  		r      Resolver
   263  		addr   string
   264  		result string
   265  		err    error
   266  	}{
   267  		{
   268  			desc: "No resolvers, returns error",
   269  			r:    NewMultiResolver(),
   270  			err:  NewNoResolverError(""),
   271  		},
   272  		{
   273  			desc:   "One default resolver, returns resolved address",
   274  			r:      NewMultiResolver(MultiResolverOptionWithResolver(ethResolve, "")),
   275  			addr:   ethAddr,
   276  			result: ethHash,
   277  		},
   278  		{
   279  			desc: "Two default resolvers, returns resolved address",
   280  			r: NewMultiResolver(
   281  				MultiResolverOptionWithResolver(ethResolve, ""),
   282  				MultiResolverOptionWithResolver(ethResolve, ""),
   283  			),
   284  			addr:   ethAddr,
   285  			result: ethHash,
   286  		},
   287  		{
   288  			desc: "Two default resolvers, first doesn't resolve, returns resolved address",
   289  			r: NewMultiResolver(
   290  				MultiResolverOptionWithResolver(doesntResolve, ""),
   291  				MultiResolverOptionWithResolver(ethResolve, ""),
   292  			),
   293  			addr:   ethAddr,
   294  			result: ethHash,
   295  		},
   296  		{
   297  			desc: "Default resolver doesn't resolve, tld resolver resolve, returns resolved address",
   298  			r: NewMultiResolver(
   299  				MultiResolverOptionWithResolver(doesntResolve, ""),
   300  				MultiResolverOptionWithResolver(ethResolve, "eth"),
   301  			),
   302  			addr:   ethAddr,
   303  			result: ethHash,
   304  		},
   305  		{
   306  			desc: "Three TLD resolvers, third resolves, returns resolved address",
   307  			r: NewMultiResolver(
   308  				MultiResolverOptionWithResolver(doesntResolve, "eth"),
   309  				MultiResolverOptionWithResolver(doesntResolve, "eth"),
   310  				MultiResolverOptionWithResolver(ethResolve, "eth"),
   311  			),
   312  			addr:   ethAddr,
   313  			result: ethHash,
   314  		},
   315  		{
   316  			desc: "One TLD resolver doesn't resolve, returns error",
   317  			r: NewMultiResolver(
   318  				MultiResolverOptionWithResolver(doesntResolve, ""),
   319  				MultiResolverOptionWithResolver(ethResolve, "eth"),
   320  			),
   321  			addr:   ethAddr,
   322  			result: ethHash,
   323  		},
   324  		{
   325  			desc: "One defautl and one TLD resolver, all doesn't resolve, returns error",
   326  			r: NewMultiResolver(
   327  				MultiResolverOptionWithResolver(doesntResolve, ""),
   328  				MultiResolverOptionWithResolver(doesntResolve, "eth"),
   329  			),
   330  			addr:   ethAddr,
   331  			result: ethHash,
   332  			err:    errors.New(`DNS name not found: "swarm.eth"`),
   333  		},
   334  		{
   335  			desc: "Two TLD resolvers, both resolve, returns resolved address",
   336  			r: NewMultiResolver(
   337  				MultiResolverOptionWithResolver(ethResolve, "eth"),
   338  				MultiResolverOptionWithResolver(testResolve, "test"),
   339  			),
   340  			addr:   testAddr,
   341  			result: testHash,
   342  		},
   343  		{
   344  			desc: "One TLD resolver, no default resolver, returns error for different TLD",
   345  			r: NewMultiResolver(
   346  				MultiResolverOptionWithResolver(ethResolve, "eth"),
   347  			),
   348  			addr: testAddr,
   349  			err:  NewNoResolverError("test"),
   350  		},
   351  	}
   352  	for _, x := range tests {
   353  		t.Run(x.desc, func(t *testing.T) {
   354  			res, err := x.r.Resolve(x.addr)
   355  			if err == nil {
   356  				if x.err != nil {
   357  					t.Fatalf("expected error %q, got result %q", x.err, res.Hex())
   358  				}
   359  				if res.Hex() != x.result {
   360  					t.Fatalf("expected result %q, got %q", x.result, res.Hex())
   361  				}
   362  			} else {
   363  				if x.err == nil {
   364  					t.Fatalf("expected no error, got %q", err)
   365  				}
   366  				if err.Error() != x.err.Error() {
   367  					t.Fatalf("expected error %q, got %q", x.err, err)
   368  				}
   369  			}
   370  		})
   371  	}
   372  }