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