github.com/vccomnet/occchain@v0.0.0-20181129092339-c57d4bab23fb/cmd/swarm/upload_test.go (about) 1 // Copyright 2017 The go-blockchain Authors 2 // This file is part of go-blockchain. 3 // 4 // go-blockchain is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU 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 // go-blockchain 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 General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-blockchain. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "bytes" 21 "fmt" 22 "io" 23 "io/ioutil" 24 "net/http" 25 "os" 26 "path" 27 "path/filepath" 28 "runtime" 29 "strings" 30 "testing" 31 "time" 32 33 "github.com/blockchain/go-blockchain/log" 34 swarm "github.com/blockchain/go-blockchain/swarm/api/client" 35 "github.com/blockchain/go-blockchain/swarm/testutil" 36 "github.com/mattn/go-colorable" 37 ) 38 39 func init() { 40 log.PrintOrigins(true) 41 log.Root().SetHandler(log.LvlFilterHandler(log.Lvl(*loglevel), log.StreamHandler(colorable.NewColorableStderr(), log.TerminalFormat(true)))) 42 } 43 44 // TestCLISwarmUp tests that running 'swarm up' makes the resulting file 45 // available from all nodes via the HTTP API 46 func TestCLISwarmUp(t *testing.T) { 47 if runtime.GOOS == "windows" { 48 t.Skip() 49 } 50 51 testCLISwarmUp(false, t) 52 } 53 func TestCLISwarmUpRecursive(t *testing.T) { 54 if runtime.GOOS == "windows" { 55 t.Skip() 56 } 57 testCLISwarmUpRecursive(false, t) 58 } 59 60 // TestCLISwarmUpEncrypted tests that running 'swarm encrypted-up' makes the resulting file 61 // available from all nodes via the HTTP API 62 func TestCLISwarmUpEncrypted(t *testing.T) { 63 if runtime.GOOS == "windows" { 64 t.Skip() 65 } 66 testCLISwarmUp(true, t) 67 } 68 func TestCLISwarmUpEncryptedRecursive(t *testing.T) { 69 if runtime.GOOS == "windows" { 70 t.Skip() 71 } 72 testCLISwarmUpRecursive(true, t) 73 } 74 75 func testCLISwarmUp(toEncrypt bool, t *testing.T) { 76 log.Info("starting 3 node cluster") 77 cluster := newTestCluster(t, 3) 78 defer cluster.Shutdown() 79 80 // create a tmp file 81 tmp, err := ioutil.TempFile("", "swarm-test") 82 if err != nil { 83 t.Fatal(err) 84 } 85 defer tmp.Close() 86 defer os.Remove(tmp.Name()) 87 88 // write data to file 89 data := "notsorandomdata" 90 _, err = io.WriteString(tmp, data) 91 if err != nil { 92 t.Fatal(err) 93 } 94 95 hashRegexp := `[a-f\d]{64}` 96 flags := []string{ 97 "--bzzapi", cluster.Nodes[0].URL, 98 "up", 99 tmp.Name()} 100 if toEncrypt { 101 hashRegexp = `[a-f\d]{128}` 102 flags = []string{ 103 "--bzzapi", cluster.Nodes[0].URL, 104 "up", 105 "--encrypt", 106 tmp.Name()} 107 } 108 // upload the file with 'swarm up' and expect a hash 109 log.Info(fmt.Sprintf("uploading file with 'swarm up'")) 110 up := runSwarm(t, flags...) 111 _, matches := up.ExpectRegexp(hashRegexp) 112 up.ExpectExit() 113 hash := matches[0] 114 log.Info("file uploaded", "hash", hash) 115 116 // get the file from the HTTP API of each node 117 for _, node := range cluster.Nodes { 118 log.Info("getting file from node", "node", node.Name) 119 120 res, err := http.Get(node.URL + "/bzz:/" + hash) 121 if err != nil { 122 t.Fatal(err) 123 } 124 defer res.Body.Close() 125 126 reply, err := ioutil.ReadAll(res.Body) 127 if err != nil { 128 t.Fatal(err) 129 } 130 if res.StatusCode != 200 { 131 t.Fatalf("expected HTTP status 200, got %s", res.Status) 132 } 133 if string(reply) != data { 134 t.Fatalf("expected HTTP body %q, got %q", data, reply) 135 } 136 log.Debug("verifying uploaded file using `swarm down`") 137 //try to get the content with `swarm down` 138 tmpDownload, err := ioutil.TempDir("", "swarm-test") 139 tmpDownload = path.Join(tmpDownload, "tmpfile.tmp") 140 if err != nil { 141 t.Fatal(err) 142 } 143 defer os.RemoveAll(tmpDownload) 144 145 bzzLocator := "bzz:/" + hash 146 flags = []string{ 147 "--bzzapi", cluster.Nodes[0].URL, 148 "down", 149 bzzLocator, 150 tmpDownload, 151 } 152 153 down := runSwarm(t, flags...) 154 down.ExpectExit() 155 156 fi, err := os.Stat(tmpDownload) 157 if err != nil { 158 t.Fatalf("could not stat path: %v", err) 159 } 160 161 switch mode := fi.Mode(); { 162 case mode.IsRegular(): 163 downloadedBytes, err := ioutil.ReadFile(tmpDownload) 164 if err != nil { 165 t.Fatalf("had an error reading the downloaded file: %v", err) 166 } 167 if !bytes.Equal(downloadedBytes, bytes.NewBufferString(data).Bytes()) { 168 t.Fatalf("retrieved data and posted data not equal!") 169 } 170 171 default: 172 t.Fatalf("expected to download regular file, got %s", fi.Mode()) 173 } 174 } 175 176 timeout := time.Duration(2 * time.Second) 177 httpClient := http.Client{ 178 Timeout: timeout, 179 } 180 181 // try to squeeze a timeout by getting an non-existent hash from each node 182 for _, node := range cluster.Nodes { 183 _, err := httpClient.Get(node.URL + "/bzz:/1023e8bae0f70be7d7b5f74343088ba408a218254391490c85ae16278e230340") 184 // we're speeding up the timeout here since netstore has a 60 seconds timeout on a request 185 if err != nil && !strings.Contains(err.Error(), "Client.Timeout exceeded while awaiting headers") { 186 t.Fatal(err) 187 } 188 // this is disabled since it takes 60s due to netstore timeout 189 // if res.StatusCode != 404 { 190 // t.Fatalf("expected HTTP status 404, got %s", res.Status) 191 // } 192 } 193 } 194 195 func testCLISwarmUpRecursive(toEncrypt bool, t *testing.T) { 196 fmt.Println("starting 3 node cluster") 197 cluster := newTestCluster(t, 3) 198 defer cluster.Shutdown() 199 200 tmpUploadDir, err := ioutil.TempDir("", "swarm-test") 201 if err != nil { 202 t.Fatal(err) 203 } 204 defer os.RemoveAll(tmpUploadDir) 205 // create tmp files 206 data := "notsorandomdata" 207 for _, path := range []string{"tmp1", "tmp2"} { 208 if err := ioutil.WriteFile(filepath.Join(tmpUploadDir, path), bytes.NewBufferString(data).Bytes(), 0644); err != nil { 209 t.Fatal(err) 210 } 211 } 212 213 hashRegexp := `[a-f\d]{64}` 214 flags := []string{ 215 "--bzzapi", cluster.Nodes[0].URL, 216 "--recursive", 217 "up", 218 tmpUploadDir} 219 if toEncrypt { 220 hashRegexp = `[a-f\d]{128}` 221 flags = []string{ 222 "--bzzapi", cluster.Nodes[0].URL, 223 "--recursive", 224 "up", 225 "--encrypt", 226 tmpUploadDir} 227 } 228 // upload the file with 'swarm up' and expect a hash 229 log.Info(fmt.Sprintf("uploading file with 'swarm up'")) 230 up := runSwarm(t, flags...) 231 _, matches := up.ExpectRegexp(hashRegexp) 232 up.ExpectExit() 233 hash := matches[0] 234 log.Info("dir uploaded", "hash", hash) 235 236 // get the file from the HTTP API of each node 237 for _, node := range cluster.Nodes { 238 log.Info("getting file from node", "node", node.Name) 239 //try to get the content with `swarm down` 240 tmpDownload, err := ioutil.TempDir("", "swarm-test") 241 if err != nil { 242 t.Fatal(err) 243 } 244 defer os.RemoveAll(tmpDownload) 245 bzzLocator := "bzz:/" + hash 246 flagss := []string{ 247 "--bzzapi", cluster.Nodes[0].URL, 248 "down", 249 "--recursive", 250 bzzLocator, 251 tmpDownload, 252 } 253 254 fmt.Println("downloading from swarm with recursive") 255 down := runSwarm(t, flagss...) 256 down.ExpectExit() 257 258 files, err := ioutil.ReadDir(tmpDownload) 259 for _, v := range files { 260 fi, err := os.Stat(path.Join(tmpDownload, v.Name())) 261 if err != nil { 262 t.Fatalf("got an error: %v", err) 263 } 264 265 switch mode := fi.Mode(); { 266 case mode.IsRegular(): 267 if file, err := swarm.Open(path.Join(tmpDownload, v.Name())); err != nil { 268 t.Fatalf("encountered an error opening the file returned from the CLI: %v", err) 269 } else { 270 ff := make([]byte, len(data)) 271 io.ReadFull(file, ff) 272 buf := bytes.NewBufferString(data) 273 274 if !bytes.Equal(ff, buf.Bytes()) { 275 t.Fatalf("retrieved data and posted data not equal!") 276 } 277 } 278 default: 279 t.Fatalf("this shouldnt happen") 280 } 281 } 282 if err != nil { 283 t.Fatalf("could not list files at: %v", files) 284 } 285 } 286 } 287 288 // TestCLISwarmUpDefaultPath tests swarm recursive upload with relative and absolute 289 // default paths and with encryption. 290 func TestCLISwarmUpDefaultPath(t *testing.T) { 291 if runtime.GOOS == "windows" { 292 t.Skip() 293 } 294 testCLISwarmUpDefaultPath(false, false, t) 295 testCLISwarmUpDefaultPath(false, true, t) 296 testCLISwarmUpDefaultPath(true, false, t) 297 testCLISwarmUpDefaultPath(true, true, t) 298 } 299 300 func testCLISwarmUpDefaultPath(toEncrypt bool, absDefaultPath bool, t *testing.T) { 301 srv := testutil.NewTestSwarmServer(t, serverFunc, nil) 302 defer srv.Close() 303 304 tmp, err := ioutil.TempDir("", "swarm-defaultpath-test") 305 if err != nil { 306 t.Fatal(err) 307 } 308 defer os.RemoveAll(tmp) 309 310 err = ioutil.WriteFile(filepath.Join(tmp, "index.html"), []byte("<h1>Test</h1>"), 0666) 311 if err != nil { 312 t.Fatal(err) 313 } 314 err = ioutil.WriteFile(filepath.Join(tmp, "robots.txt"), []byte("Disallow: /"), 0666) 315 if err != nil { 316 t.Fatal(err) 317 } 318 319 defaultPath := "index.html" 320 if absDefaultPath { 321 defaultPath = filepath.Join(tmp, defaultPath) 322 } 323 324 args := []string{ 325 "--bzzapi", 326 srv.URL, 327 "--recursive", 328 "--defaultpath", 329 defaultPath, 330 "up", 331 tmp, 332 } 333 if toEncrypt { 334 args = append(args, "--encrypt") 335 } 336 337 up := runSwarm(t, args...) 338 hashRegexp := `[a-f\d]{64,128}` 339 _, matches := up.ExpectRegexp(hashRegexp) 340 up.ExpectExit() 341 hash := matches[0] 342 343 client := swarm.NewClient(srv.URL) 344 345 m, isEncrypted, err := client.DownloadManifest(hash) 346 if err != nil { 347 t.Fatal(err) 348 } 349 350 if toEncrypt != isEncrypted { 351 t.Error("downloaded manifest is not encrypted") 352 } 353 354 var found bool 355 var entriesCount int 356 for _, e := range m.Entries { 357 entriesCount++ 358 if e.Path == "" { 359 found = true 360 } 361 } 362 363 if !found { 364 t.Error("manifest default entry was not found") 365 } 366 367 if entriesCount != 3 { 368 t.Errorf("manifest contains %v entries, expected %v", entriesCount, 3) 369 } 370 }