github.com/avahowell/sia@v0.5.1-beta.0.20160524050156-83dcc3d37c94/modules/renter/upload_test.go (about)

     1  package renter
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"path/filepath"
     7  	"sync"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/NebulousLabs/Sia/build"
    12  	"github.com/NebulousLabs/Sia/crypto"
    13  	"github.com/NebulousLabs/Sia/modules"
    14  	"github.com/NebulousLabs/Sia/modules/renter/contractor"
    15  	"github.com/NebulousLabs/Sia/types"
    16  )
    17  
    18  // uploadDownloadContractor is a mocked hostContractor, contractor.Editor, and contractor.Downloader. It is
    19  // used for testing the uploading and downloading functions of the renter.
    20  type uploadDownloadContractor struct {
    21  	stubContractor
    22  	sectors map[crypto.Hash][]byte
    23  	mu      sync.Mutex
    24  }
    25  
    26  func (uc *uploadDownloadContractor) Contracts() []modules.RenterContract {
    27  	return make([]modules.RenterContract, 24) // exact number shouldn't matter, as long as its large enough
    28  }
    29  
    30  // Editor simply returns the uploadDownloadContractor, since it also implements the
    31  // Editor interface.
    32  func (uc *uploadDownloadContractor) Editor(modules.RenterContract) (contractor.Editor, error) {
    33  	return uc, nil
    34  }
    35  
    36  // Downloader simply returns the uploadDownloadContractor, since it also
    37  // implements the Downloader interface.
    38  func (uc *uploadDownloadContractor) Downloader(modules.RenterContract) (contractor.Downloader, error) {
    39  	return uc, nil
    40  }
    41  
    42  // Upload simulates a successful data upload.
    43  func (uc *uploadDownloadContractor) Upload(data []byte) (crypto.Hash, error) {
    44  	uc.mu.Lock()
    45  	defer uc.mu.Unlock()
    46  	root := crypto.MerkleRoot(data)
    47  	uc.sectors[root] = data
    48  	return root, nil
    49  }
    50  
    51  // Download simulates a successful data download.
    52  func (uc *uploadDownloadContractor) Sector(root crypto.Hash) ([]byte, error) {
    53  	uc.mu.Lock()
    54  	defer uc.mu.Unlock()
    55  	return uc.sectors[root], nil
    56  }
    57  
    58  // stub implementations of the contractor.Editor methods
    59  func (*uploadDownloadContractor) Address() modules.NetAddress                           { return "" }
    60  func (*uploadDownloadContractor) Delete(crypto.Hash) error                              { return nil }
    61  func (*uploadDownloadContractor) Modify(crypto.Hash, crypto.Hash, uint64, []byte) error { return nil }
    62  func (*uploadDownloadContractor) ContractID() types.FileContractID                      { return types.FileContractID{} }
    63  func (*uploadDownloadContractor) EndHeight() types.BlockHeight                          { return 10000 }
    64  func (*uploadDownloadContractor) Close() error                                          { return nil }
    65  
    66  // TestUploadDownload tests the Upload and Download methods using a mock
    67  // contractor.
    68  func TestUploadDownload(t *testing.T) {
    69  	if testing.Short() {
    70  		t.SkipNow()
    71  	}
    72  
    73  	// create renter with mocked contractor
    74  	hc := &uploadDownloadContractor{
    75  		sectors: make(map[crypto.Hash][]byte),
    76  	}
    77  	rt, err := newContractorTester("TestUploadDownload", hc)
    78  	if err != nil {
    79  		t.Fatal(err)
    80  	}
    81  
    82  	// create a file
    83  	data, err := crypto.RandBytes(777)
    84  	if err != nil {
    85  		t.Fatal(err)
    86  	}
    87  	source := filepath.Join(build.SiaTestingDir, "renter", "TestUploadDownload", "test.dat")
    88  	err = ioutil.WriteFile(source, data, 0600)
    89  	if err != nil {
    90  		t.Fatal(err)
    91  	}
    92  
    93  	// use 1-1 erasure code, because we'll only have one host
    94  	rsc, _ := NewRSCode(1, 1)
    95  
    96  	// upload file
    97  	err = rt.renter.Upload(modules.FileUploadParams{
    98  		Source:      source,
    99  		SiaPath:     "foo",
   100  		ErasureCode: rsc,
   101  		// Upload will use sane defaults for other params
   102  	})
   103  	if err != nil {
   104  		t.Fatal(err)
   105  	}
   106  	files := rt.renter.FileList()
   107  	if len(files) != 1 {
   108  		t.Fatal("expected 1 file, got", len(files))
   109  	}
   110  
   111  	// wait for repair loop for fully upload file
   112  	for i := 0; i < 10 && !files[0].Available; i++ {
   113  		files = rt.renter.FileList()
   114  		time.Sleep(time.Second)
   115  	}
   116  	if !files[0].Available {
   117  		t.Fatal("file did not reach full availability:", files[0].UploadProgress)
   118  	}
   119  
   120  	// download the file
   121  	dest := filepath.Join(build.SiaTestingDir, "renter", "TestUploadDownload", "test.dat")
   122  	err = rt.renter.Download("foo", dest)
   123  	if err != nil {
   124  		t.Fatal(err)
   125  	}
   126  
   127  	downData, err := ioutil.ReadFile(dest)
   128  	if err != nil {
   129  		t.Fatal(err)
   130  	}
   131  	if !bytes.Equal(downData, data) {
   132  		t.Fatal("recovered data does not match original")
   133  	}
   134  }