github.com/gobitfly/go-ethereum@v1.8.12/swarm/swarm_test.go (about) 1 // Copyright 2017 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 swarm 18 19 import ( 20 "io/ioutil" 21 "math/rand" 22 "os" 23 "path" 24 "strings" 25 "testing" 26 "time" 27 28 "github.com/ethereum/go-ethereum/common" 29 "github.com/ethereum/go-ethereum/crypto" 30 "github.com/ethereum/go-ethereum/rpc" 31 "github.com/ethereum/go-ethereum/swarm/api" 32 ) 33 34 // TestNewSwarm validates Swarm fields in repsect to the provided configuration. 35 func TestNewSwarm(t *testing.T) { 36 dir, err := ioutil.TempDir("", "swarm") 37 if err != nil { 38 t.Fatal(err) 39 } 40 defer os.RemoveAll(dir) 41 42 // a simple rpc endpoint for testing dialing 43 ipcEndpoint := path.Join(dir, "TestSwarm.ipc") 44 45 _, server, err := rpc.StartIPCEndpoint(ipcEndpoint, nil) 46 if err != nil { 47 t.Error(err) 48 } 49 defer server.Stop() 50 51 for _, tc := range []struct { 52 name string 53 configure func(*api.Config) 54 check func(*testing.T, *Swarm, *api.Config) 55 }{ 56 { 57 name: "defaults", 58 configure: nil, 59 check: func(t *testing.T, s *Swarm, config *api.Config) { 60 if s.config != config { 61 t.Error("config is not the same object") 62 } 63 if s.backend != nil { 64 t.Error("backend is not nil") 65 } 66 if s.privateKey == nil { 67 t.Error("private key is not set") 68 } 69 if !s.config.HiveParams.Discovery { 70 t.Error("config.HiveParams.Discovery is false, must be true regardless the configuration") 71 } 72 if s.dns != nil { 73 t.Error("dns initialized, but it should not be") 74 } 75 if s.lstore == nil { 76 t.Error("localstore not initialized") 77 } 78 if s.streamer == nil { 79 t.Error("streamer not initialized") 80 } 81 if s.fileStore == nil { 82 t.Error("fileStore not initialized") 83 } 84 if s.lstore.Validators == nil { 85 t.Error("localstore validators not initialized") 86 } 87 if s.bzz == nil { 88 t.Error("bzz not initialized") 89 } 90 if s.ps == nil { 91 t.Error("pss not initialized") 92 } 93 if s.api == nil { 94 t.Error("api not initialized") 95 } 96 if s.sfs == nil { 97 t.Error("swarm filesystem not initialized") 98 } 99 }, 100 }, 101 { 102 name: "with swap", 103 configure: func(config *api.Config) { 104 config.SwapAPI = ipcEndpoint 105 config.SwapEnabled = true 106 }, 107 check: func(t *testing.T, s *Swarm, _ *api.Config) { 108 if s.backend == nil { 109 t.Error("backend is nil") 110 } 111 }, 112 }, 113 { 114 name: "with swap disabled", 115 configure: func(config *api.Config) { 116 config.SwapAPI = ipcEndpoint 117 config.SwapEnabled = false 118 }, 119 check: func(t *testing.T, s *Swarm, _ *api.Config) { 120 if s.backend != nil { 121 t.Error("backend is not nil") 122 } 123 }, 124 }, 125 { 126 name: "with swap enabled and api endpoint blank", 127 configure: func(config *api.Config) { 128 config.SwapAPI = "" 129 config.SwapEnabled = true 130 }, 131 check: func(t *testing.T, s *Swarm, _ *api.Config) { 132 if s.backend != nil { 133 t.Error("backend is not nil") 134 } 135 }, 136 }, 137 { 138 name: "ens", 139 configure: func(config *api.Config) { 140 config.EnsAPIs = []string{ 141 "http://127.0.0.1:8888", 142 } 143 }, 144 check: func(t *testing.T, s *Swarm, _ *api.Config) { 145 if s.dns == nil { 146 t.Error("dns is not initialized") 147 } 148 }, 149 }, 150 } { 151 t.Run(tc.name, func(t *testing.T) { 152 config := api.NewConfig() 153 154 dir, err := ioutil.TempDir("", "swarm") 155 if err != nil { 156 t.Fatal(err) 157 } 158 defer os.RemoveAll(dir) 159 160 config.Path = dir 161 162 privkey, err := crypto.GenerateKey() 163 if err != nil { 164 t.Fatal(err) 165 } 166 167 config.Init(privkey) 168 169 if tc.configure != nil { 170 tc.configure(config) 171 } 172 173 s, err := NewSwarm(config, nil) 174 if err != nil { 175 t.Fatal(err) 176 } 177 178 if tc.check != nil { 179 tc.check(t, s, config) 180 } 181 }) 182 } 183 } 184 185 func TestParseEnsAPIAddress(t *testing.T) { 186 for _, x := range []struct { 187 description string 188 value string 189 tld string 190 endpoint string 191 addr common.Address 192 }{ 193 { 194 description: "IPC endpoint", 195 value: "/data/testnet/geth.ipc", 196 endpoint: "/data/testnet/geth.ipc", 197 }, 198 { 199 description: "HTTP endpoint", 200 value: "http://127.0.0.1:1234", 201 endpoint: "http://127.0.0.1:1234", 202 }, 203 { 204 description: "WS endpoint", 205 value: "ws://127.0.0.1:1234", 206 endpoint: "ws://127.0.0.1:1234", 207 }, 208 { 209 description: "IPC Endpoint and TLD", 210 value: "test:/data/testnet/geth.ipc", 211 endpoint: "/data/testnet/geth.ipc", 212 tld: "test", 213 }, 214 { 215 description: "HTTP endpoint and TLD", 216 value: "test:http://127.0.0.1:1234", 217 endpoint: "http://127.0.0.1:1234", 218 tld: "test", 219 }, 220 { 221 description: "WS endpoint and TLD", 222 value: "test:ws://127.0.0.1:1234", 223 endpoint: "ws://127.0.0.1:1234", 224 tld: "test", 225 }, 226 { 227 description: "IPC Endpoint and contract address", 228 value: "314159265dD8dbb310642f98f50C066173C1259b@/data/testnet/geth.ipc", 229 endpoint: "/data/testnet/geth.ipc", 230 addr: common.HexToAddress("314159265dD8dbb310642f98f50C066173C1259b"), 231 }, 232 { 233 description: "HTTP endpoint and contract address", 234 value: "314159265dD8dbb310642f98f50C066173C1259b@http://127.0.0.1:1234", 235 endpoint: "http://127.0.0.1:1234", 236 addr: common.HexToAddress("314159265dD8dbb310642f98f50C066173C1259b"), 237 }, 238 { 239 description: "WS endpoint and contract address", 240 value: "314159265dD8dbb310642f98f50C066173C1259b@ws://127.0.0.1:1234", 241 endpoint: "ws://127.0.0.1:1234", 242 addr: common.HexToAddress("314159265dD8dbb310642f98f50C066173C1259b"), 243 }, 244 { 245 description: "IPC Endpoint, TLD and contract address", 246 value: "test:314159265dD8dbb310642f98f50C066173C1259b@/data/testnet/geth.ipc", 247 endpoint: "/data/testnet/geth.ipc", 248 addr: common.HexToAddress("314159265dD8dbb310642f98f50C066173C1259b"), 249 tld: "test", 250 }, 251 { 252 description: "HTTP endpoint, TLD and contract address", 253 value: "eth:314159265dD8dbb310642f98f50C066173C1259b@http://127.0.0.1:1234", 254 endpoint: "http://127.0.0.1:1234", 255 addr: common.HexToAddress("314159265dD8dbb310642f98f50C066173C1259b"), 256 tld: "eth", 257 }, 258 { 259 description: "WS endpoint, TLD and contract address", 260 value: "eth:314159265dD8dbb310642f98f50C066173C1259b@ws://127.0.0.1:1234", 261 endpoint: "ws://127.0.0.1:1234", 262 addr: common.HexToAddress("314159265dD8dbb310642f98f50C066173C1259b"), 263 tld: "eth", 264 }, 265 } { 266 t.Run(x.description, func(t *testing.T) { 267 tld, endpoint, addr := parseEnsAPIAddress(x.value) 268 if endpoint != x.endpoint { 269 t.Errorf("expected Endpoint %q, got %q", x.endpoint, endpoint) 270 } 271 if addr != x.addr { 272 t.Errorf("expected ContractAddress %q, got %q", x.addr.String(), addr.String()) 273 } 274 if tld != x.tld { 275 t.Errorf("expected TLD %q, got %q", x.tld, tld) 276 } 277 }) 278 } 279 } 280 281 // TestLocalStoreAndRetrieve runs multiple tests where different size files are uploaded 282 // to a single Swarm instance using API Store and checked against the content returned 283 // by API Retrieve function. 284 // 285 // This test is intended to validate functionality of chunker store and join functions 286 // and their intergartion into Swarm, without comparing results with ones produced by 287 // another chunker implementation, as it is done in swarm/storage tests. 288 func TestLocalStoreAndRetrieve(t *testing.T) { 289 config := api.NewConfig() 290 291 dir, err := ioutil.TempDir("", "node") 292 if err != nil { 293 t.Fatal(err) 294 } 295 defer os.RemoveAll(dir) 296 297 config.Path = dir 298 299 privkey, err := crypto.GenerateKey() 300 if err != nil { 301 t.Fatal(err) 302 } 303 304 config.Init(privkey) 305 306 swarm, err := NewSwarm(config, nil) 307 if err != nil { 308 t.Fatal(err) 309 } 310 311 // by default, test only the lonely chunk cases 312 sizes := []int{1, 60, 4097, 524288 + 1, 7*524288 + 1, 128*524288 + 1} 313 314 if *longrunning { 315 // test broader set of cases if -longruning flag is set 316 sizes = append(sizes, 83, 179, 253, 1024, 4095, 4096, 8191, 8192, 8193, 12287, 12288, 12289, 123456, 2345678, 67298391, 524288, 524288+4096, 524288+4097, 7*524288, 7*524288+4096, 7*524288+4097, 128*524288, 128*524288+4096, 128*524288+4097, 816778334) 317 } 318 for _, n := range sizes { 319 testLocalStoreAndRetrieve(t, swarm, n, true) 320 testLocalStoreAndRetrieve(t, swarm, n, false) 321 } 322 } 323 324 // testLocalStoreAndRetrieve is using a single Swarm instance, to upload 325 // a file of length n with optional random data using API Store function, 326 // and checks the output of API Retrieve function on the same instance. 327 // This is a regression test for issue 328 // https://github.com/ethersphere/go-ethereum/issues/639 329 // where pyramid chunker did not split correctly files with lengths that 330 // are edge cases for chunk and tree parameters, depending whether there 331 // is a tree chunk with only one data chunk and how the compress functionality 332 // changed the tree. 333 func testLocalStoreAndRetrieve(t *testing.T, swarm *Swarm, n int, randomData bool) { 334 slice := make([]byte, n) 335 if randomData { 336 rand.Seed(time.Now().UnixNano()) 337 rand.Read(slice) 338 } 339 dataPut := string(slice) 340 341 k, wait, err := swarm.api.Store(strings.NewReader(dataPut), int64(len(dataPut)), false) 342 if err != nil { 343 t.Fatal(err) 344 } 345 if wait != nil { 346 wait() 347 } 348 349 r, _ := swarm.api.Retrieve(k) 350 351 d, err := ioutil.ReadAll(r) 352 if err != nil { 353 t.Fatal(err) 354 } 355 dataGet := string(d) 356 357 if len(dataPut) != len(dataGet) { 358 t.Fatalf("data not matched: length expected %v, got %v", len(dataPut), len(dataGet)) 359 } else { 360 if dataPut != dataGet { 361 t.Fatal("data not matched") 362 } 363 } 364 }