github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/swarm/api/api_test.go (about)

     1  // This file is part of the go-sberex library. The go-sberex library is 
     2  // free software: you can redistribute it and/or modify it under the terms 
     3  // of the GNU Lesser General Public License as published by the Free 
     4  // Software Foundation, either version 3 of the License, or (at your option)
     5  // any later version.
     6  //
     7  // The go-sberex library is distributed in the hope that it will be useful, 
     8  // but WITHOUT ANY WARRANTY; without even the implied warranty of
     9  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
    10  // General Public License <http://www.gnu.org/licenses/> for more details.
    11  
    12  package api
    13  
    14  import (
    15  	"errors"
    16  	"fmt"
    17  	"io"
    18  	"io/ioutil"
    19  	"os"
    20  	"testing"
    21  
    22  	"github.com/Sberex/go-sberex/common"
    23  	"github.com/Sberex/go-sberex/log"
    24  	"github.com/Sberex/go-sberex/swarm/storage"
    25  )
    26  
    27  func testApi(t *testing.T, f func(*Api)) {
    28  	datadir, err := ioutil.TempDir("", "bzz-test")
    29  	if err != nil {
    30  		t.Fatalf("unable to create temp dir: %v", err)
    31  	}
    32  	os.RemoveAll(datadir)
    33  	defer os.RemoveAll(datadir)
    34  	dpa, err := storage.NewLocalDPA(datadir)
    35  	if err != nil {
    36  		return
    37  	}
    38  	api := NewApi(dpa, nil)
    39  	dpa.Start()
    40  	f(api)
    41  	dpa.Stop()
    42  }
    43  
    44  type testResponse struct {
    45  	reader storage.LazySectionReader
    46  	*Response
    47  }
    48  
    49  func checkResponse(t *testing.T, resp *testResponse, exp *Response) {
    50  
    51  	if resp.MimeType != exp.MimeType {
    52  		t.Errorf("incorrect mimeType. expected '%s', got '%s'", exp.MimeType, resp.MimeType)
    53  	}
    54  	if resp.Status != exp.Status {
    55  		t.Errorf("incorrect status. expected '%d', got '%d'", exp.Status, resp.Status)
    56  	}
    57  	if resp.Size != exp.Size {
    58  		t.Errorf("incorrect size. expected '%d', got '%d'", exp.Size, resp.Size)
    59  	}
    60  	if resp.reader != nil {
    61  		content := make([]byte, resp.Size)
    62  		read, _ := resp.reader.Read(content)
    63  		if int64(read) != exp.Size {
    64  			t.Errorf("incorrect content length. expected '%d...', got '%d...'", read, exp.Size)
    65  		}
    66  		resp.Content = string(content)
    67  	}
    68  	if resp.Content != exp.Content {
    69  		// if !bytes.Equal(resp.Content, exp.Content)
    70  		t.Errorf("incorrect content. expected '%s...', got '%s...'", string(exp.Content), string(resp.Content))
    71  	}
    72  }
    73  
    74  // func expResponse(content []byte, mimeType string, status int) *Response {
    75  func expResponse(content string, mimeType string, status int) *Response {
    76  	log.Trace(fmt.Sprintf("expected content (%v): %v ", len(content), content))
    77  	return &Response{mimeType, status, int64(len(content)), content}
    78  }
    79  
    80  // func testGet(t *testing.T, api *Api, bzzhash string) *testResponse {
    81  func testGet(t *testing.T, api *Api, bzzhash, path string) *testResponse {
    82  	key := storage.Key(common.Hex2Bytes(bzzhash))
    83  	reader, mimeType, status, err := api.Get(key, path)
    84  	if err != nil {
    85  		t.Fatalf("unexpected error: %v", err)
    86  	}
    87  	quitC := make(chan bool)
    88  	size, err := reader.Size(quitC)
    89  	if err != nil {
    90  		t.Fatalf("unexpected error: %v", err)
    91  	}
    92  	log.Trace(fmt.Sprintf("reader size: %v ", size))
    93  	s := make([]byte, size)
    94  	_, err = reader.Read(s)
    95  	if err != io.EOF {
    96  		t.Fatalf("unexpected error: %v", err)
    97  	}
    98  	reader.Seek(0, 0)
    99  	return &testResponse{reader, &Response{mimeType, status, size, string(s)}}
   100  	// return &testResponse{reader, &Response{mimeType, status, reader.Size(), nil}}
   101  }
   102  
   103  func TestApiPut(t *testing.T) {
   104  	testApi(t, func(api *Api) {
   105  		content := "hello"
   106  		exp := expResponse(content, "text/plain", 0)
   107  		// exp := expResponse([]byte(content), "text/plain", 0)
   108  		key, err := api.Put(content, exp.MimeType)
   109  		if err != nil {
   110  			t.Fatalf("unexpected error: %v", err)
   111  		}
   112  		resp := testGet(t, api, key.String(), "")
   113  		checkResponse(t, resp, exp)
   114  	})
   115  }
   116  
   117  // testResolver implements the Resolver interface and either returns the given
   118  // hash if it is set, or returns a "name not found" error
   119  type testResolver struct {
   120  	hash *common.Hash
   121  }
   122  
   123  func newTestResolver(addr string) *testResolver {
   124  	r := &testResolver{}
   125  	if addr != "" {
   126  		hash := common.HexToHash(addr)
   127  		r.hash = &hash
   128  	}
   129  	return r
   130  }
   131  
   132  func (t *testResolver) Resolve(addr string) (common.Hash, error) {
   133  	if t.hash == nil {
   134  		return common.Hash{}, fmt.Errorf("DNS name not found: %q", addr)
   135  	}
   136  	return *t.hash, nil
   137  }
   138  
   139  // TestAPIResolve tests resolving URIs which can either contain content hashes
   140  // or ENS names
   141  func TestAPIResolve(t *testing.T) {
   142  	ensAddr := "swarm.eth"
   143  	hashAddr := "1111111111111111111111111111111111111111111111111111111111111111"
   144  	resolvedAddr := "2222222222222222222222222222222222222222222222222222222222222222"
   145  	doesResolve := newTestResolver(resolvedAddr)
   146  	doesntResolve := newTestResolver("")
   147  
   148  	type test struct {
   149  		desc      string
   150  		dns       Resolver
   151  		addr      string
   152  		immutable bool
   153  		result    string
   154  		expectErr error
   155  	}
   156  
   157  	tests := []*test{
   158  		{
   159  			desc:   "DNS not configured, hash address, returns hash address",
   160  			dns:    nil,
   161  			addr:   hashAddr,
   162  			result: hashAddr,
   163  		},
   164  		{
   165  			desc:      "DNS not configured, ENS address, returns error",
   166  			dns:       nil,
   167  			addr:      ensAddr,
   168  			expectErr: errors.New(`no DNS to resolve name: "swarm.eth"`),
   169  		},
   170  		{
   171  			desc:   "DNS configured, hash address, hash resolves, returns resolved address",
   172  			dns:    doesResolve,
   173  			addr:   hashAddr,
   174  			result: resolvedAddr,
   175  		},
   176  		{
   177  			desc:      "DNS configured, immutable hash address, hash resolves, returns hash address",
   178  			dns:       doesResolve,
   179  			addr:      hashAddr,
   180  			immutable: true,
   181  			result:    hashAddr,
   182  		},
   183  		{
   184  			desc:   "DNS configured, hash address, hash doesn't resolve, returns hash address",
   185  			dns:    doesntResolve,
   186  			addr:   hashAddr,
   187  			result: hashAddr,
   188  		},
   189  		{
   190  			desc:   "DNS configured, ENS address, name resolves, returns resolved address",
   191  			dns:    doesResolve,
   192  			addr:   ensAddr,
   193  			result: resolvedAddr,
   194  		},
   195  		{
   196  			desc:      "DNS configured, immutable ENS address, name resolves, returns error",
   197  			dns:       doesResolve,
   198  			addr:      ensAddr,
   199  			immutable: true,
   200  			expectErr: errors.New(`immutable address not a content hash: "swarm.eth"`),
   201  		},
   202  		{
   203  			desc:      "DNS configured, ENS address, name doesn't resolve, returns error",
   204  			dns:       doesntResolve,
   205  			addr:      ensAddr,
   206  			expectErr: errors.New(`DNS name not found: "swarm.eth"`),
   207  		},
   208  	}
   209  	for _, x := range tests {
   210  		t.Run(x.desc, func(t *testing.T) {
   211  			api := &Api{dns: x.dns}
   212  			uri := &URI{Addr: x.addr, Scheme: "bzz"}
   213  			if x.immutable {
   214  				uri.Scheme = "bzz-immutable"
   215  			}
   216  			res, err := api.Resolve(uri)
   217  			if err == nil {
   218  				if x.expectErr != nil {
   219  					t.Fatalf("expected error %q, got result %q", x.expectErr, res)
   220  				}
   221  				if res.String() != x.result {
   222  					t.Fatalf("expected result %q, got %q", x.result, res)
   223  				}
   224  			} else {
   225  				if x.expectErr == nil {
   226  					t.Fatalf("expected no error, got %q", err)
   227  				}
   228  				if err.Error() != x.expectErr.Error() {
   229  					t.Fatalf("expected error %q, got %q", x.expectErr, err)
   230  				}
   231  			}
   232  		})
   233  	}
   234  }
   235  
   236  func TestMultiResolver(t *testing.T) {
   237  	doesntResolve := newTestResolver("")
   238  
   239  	ethAddr := "swarm.eth"
   240  	ethHash := "0x2222222222222222222222222222222222222222222222222222222222222222"
   241  	ethResolve := newTestResolver(ethHash)
   242  
   243  	testAddr := "swarm.test"
   244  	testHash := "0x1111111111111111111111111111111111111111111111111111111111111111"
   245  	testResolve := newTestResolver(testHash)
   246  
   247  	tests := []struct {
   248  		desc   string
   249  		r      Resolver
   250  		addr   string
   251  		result string
   252  		err    error
   253  	}{
   254  		{
   255  			desc: "No resolvers, returns error",
   256  			r:    NewMultiResolver(),
   257  			err:  NewNoResolverError(""),
   258  		},
   259  		{
   260  			desc:   "One default resolver, returns resolved address",
   261  			r:      NewMultiResolver(MultiResolverOptionWithResolver(ethResolve, "")),
   262  			addr:   ethAddr,
   263  			result: ethHash,
   264  		},
   265  		{
   266  			desc: "Two default resolvers, returns resolved address",
   267  			r: NewMultiResolver(
   268  				MultiResolverOptionWithResolver(ethResolve, ""),
   269  				MultiResolverOptionWithResolver(ethResolve, ""),
   270  			),
   271  			addr:   ethAddr,
   272  			result: ethHash,
   273  		},
   274  		{
   275  			desc: "Two default resolvers, first doesn't resolve, returns resolved address",
   276  			r: NewMultiResolver(
   277  				MultiResolverOptionWithResolver(doesntResolve, ""),
   278  				MultiResolverOptionWithResolver(ethResolve, ""),
   279  			),
   280  			addr:   ethAddr,
   281  			result: ethHash,
   282  		},
   283  		{
   284  			desc: "Default resolver doesn't resolve, tld resolver resolve, returns resolved address",
   285  			r: NewMultiResolver(
   286  				MultiResolverOptionWithResolver(doesntResolve, ""),
   287  				MultiResolverOptionWithResolver(ethResolve, "eth"),
   288  			),
   289  			addr:   ethAddr,
   290  			result: ethHash,
   291  		},
   292  		{
   293  			desc: "Three TLD resolvers, third resolves, returns resolved address",
   294  			r: NewMultiResolver(
   295  				MultiResolverOptionWithResolver(doesntResolve, "eth"),
   296  				MultiResolverOptionWithResolver(doesntResolve, "eth"),
   297  				MultiResolverOptionWithResolver(ethResolve, "eth"),
   298  			),
   299  			addr:   ethAddr,
   300  			result: ethHash,
   301  		},
   302  		{
   303  			desc: "One TLD resolver doesn't resolve, returns error",
   304  			r: NewMultiResolver(
   305  				MultiResolverOptionWithResolver(doesntResolve, ""),
   306  				MultiResolverOptionWithResolver(ethResolve, "eth"),
   307  			),
   308  			addr:   ethAddr,
   309  			result: ethHash,
   310  		},
   311  		{
   312  			desc: "One defautl and one TLD resolver, all doesn't resolve, returns error",
   313  			r: NewMultiResolver(
   314  				MultiResolverOptionWithResolver(doesntResolve, ""),
   315  				MultiResolverOptionWithResolver(doesntResolve, "eth"),
   316  			),
   317  			addr:   ethAddr,
   318  			result: ethHash,
   319  			err:    errors.New(`DNS name not found: "swarm.eth"`),
   320  		},
   321  		{
   322  			desc: "Two TLD resolvers, both resolve, returns resolved address",
   323  			r: NewMultiResolver(
   324  				MultiResolverOptionWithResolver(ethResolve, "eth"),
   325  				MultiResolverOptionWithResolver(testResolve, "test"),
   326  			),
   327  			addr:   testAddr,
   328  			result: testHash,
   329  		},
   330  		{
   331  			desc: "One TLD resolver, no default resolver, returns error for different TLD",
   332  			r: NewMultiResolver(
   333  				MultiResolverOptionWithResolver(ethResolve, "eth"),
   334  			),
   335  			addr: testAddr,
   336  			err:  NewNoResolverError("test"),
   337  		},
   338  	}
   339  	for _, x := range tests {
   340  		t.Run(x.desc, func(t *testing.T) {
   341  			res, err := x.r.Resolve(x.addr)
   342  			if err == nil {
   343  				if x.err != nil {
   344  					t.Fatalf("expected error %q, got result %q", x.err, res.Hex())
   345  				}
   346  				if res.Hex() != x.result {
   347  					t.Fatalf("expected result %q, got %q", x.result, res.Hex())
   348  				}
   349  			} else {
   350  				if x.err == nil {
   351  					t.Fatalf("expected no error, got %q", err)
   352  				}
   353  				if err.Error() != x.err.Error() {
   354  					t.Fatalf("expected error %q, got %q", x.err, err)
   355  				}
   356  			}
   357  		})
   358  	}
   359  }