github.com/johnathanhowell/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 }