api_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. // Copyright 2016 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. package api
  17. import (
  18. "context"
  19. "errors"
  20. "flag"
  21. "fmt"
  22. "io"
  23. "io/ioutil"
  24. "math/big"
  25. "os"
  26. "testing"
  27. "github.com/ethereum/go-ethereum/common"
  28. "github.com/ethereum/go-ethereum/core/types"
  29. "github.com/ethereum/go-ethereum/log"
  30. "github.com/ethereum/go-ethereum/swarm/sctx"
  31. "github.com/ethereum/go-ethereum/swarm/storage"
  32. )
  33. func init() {
  34. loglevel := flag.Int("loglevel", 2, "loglevel")
  35. flag.Parse()
  36. log.Root().SetHandler(log.CallerFileHandler(log.LvlFilterHandler(log.Lvl(*loglevel), log.StreamHandler(os.Stderr, log.TerminalFormat(true)))))
  37. }
  38. func testAPI(t *testing.T, f func(*API, bool)) {
  39. datadir, err := ioutil.TempDir("", "bzz-test")
  40. if err != nil {
  41. t.Fatalf("unable to create temp dir: %v", err)
  42. }
  43. defer os.RemoveAll(datadir)
  44. fileStore, err := storage.NewLocalFileStore(datadir, make([]byte, 32))
  45. if err != nil {
  46. return
  47. }
  48. api := NewAPI(fileStore, nil, nil, nil)
  49. f(api, false)
  50. f(api, true)
  51. }
  52. type testResponse struct {
  53. reader storage.LazySectionReader
  54. *Response
  55. }
  56. func checkResponse(t *testing.T, resp *testResponse, exp *Response) {
  57. if resp.MimeType != exp.MimeType {
  58. t.Errorf("incorrect mimeType. expected '%s', got '%s'", exp.MimeType, resp.MimeType)
  59. }
  60. if resp.Status != exp.Status {
  61. t.Errorf("incorrect status. expected '%d', got '%d'", exp.Status, resp.Status)
  62. }
  63. if resp.Size != exp.Size {
  64. t.Errorf("incorrect size. expected '%d', got '%d'", exp.Size, resp.Size)
  65. }
  66. if resp.reader != nil {
  67. content := make([]byte, resp.Size)
  68. read, _ := resp.reader.Read(content)
  69. if int64(read) != exp.Size {
  70. t.Errorf("incorrect content length. expected '%d...', got '%d...'", read, exp.Size)
  71. }
  72. resp.Content = string(content)
  73. }
  74. if resp.Content != exp.Content {
  75. // if !bytes.Equal(resp.Content, exp.Content)
  76. t.Errorf("incorrect content. expected '%s...', got '%s...'", string(exp.Content), string(resp.Content))
  77. }
  78. }
  79. // func expResponse(content []byte, mimeType string, status int) *Response {
  80. func expResponse(content string, mimeType string, status int) *Response {
  81. log.Trace(fmt.Sprintf("expected content (%v): %v ", len(content), content))
  82. return &Response{mimeType, status, int64(len(content)), content}
  83. }
  84. func testGet(t *testing.T, api *API, bzzhash, path string) *testResponse {
  85. addr := storage.Address(common.Hex2Bytes(bzzhash))
  86. reader, mimeType, status, _, err := api.Get(context.TODO(), NOOPDecrypt, addr, path)
  87. if err != nil {
  88. t.Fatalf("unexpected error: %v", err)
  89. }
  90. quitC := make(chan bool)
  91. size, err := reader.Size(context.TODO(), quitC)
  92. if err != nil {
  93. t.Fatalf("unexpected error: %v", err)
  94. }
  95. log.Trace(fmt.Sprintf("reader size: %v ", size))
  96. s := make([]byte, size)
  97. _, err = reader.Read(s)
  98. if err != io.EOF {
  99. t.Fatalf("unexpected error: %v", err)
  100. }
  101. reader.Seek(0, 0)
  102. return &testResponse{reader, &Response{mimeType, status, size, string(s)}}
  103. // return &testResponse{reader, &Response{mimeType, status, reader.Size(), nil}}
  104. }
  105. func TestApiPut(t *testing.T) {
  106. testAPI(t, func(api *API, toEncrypt bool) {
  107. content := "hello"
  108. exp := expResponse(content, "text/plain", 0)
  109. ctx := context.TODO()
  110. addr, wait, err := api.Put(ctx, content, exp.MimeType, toEncrypt)
  111. if err != nil {
  112. t.Fatalf("unexpected error: %v", err)
  113. }
  114. err = wait(ctx)
  115. if err != nil {
  116. t.Fatalf("unexpected error: %v", err)
  117. }
  118. resp := testGet(t, api, addr.Hex(), "")
  119. checkResponse(t, resp, exp)
  120. })
  121. }
  122. // testResolver implements the Resolver interface and either returns the given
  123. // hash if it is set, or returns a "name not found" error
  124. type testResolveValidator struct {
  125. hash *common.Hash
  126. }
  127. func newTestResolveValidator(addr string) *testResolveValidator {
  128. r := &testResolveValidator{}
  129. if addr != "" {
  130. hash := common.HexToHash(addr)
  131. r.hash = &hash
  132. }
  133. return r
  134. }
  135. func (t *testResolveValidator) Resolve(addr string) (common.Hash, error) {
  136. if t.hash == nil {
  137. return common.Hash{}, fmt.Errorf("DNS name not found: %q", addr)
  138. }
  139. return *t.hash, nil
  140. }
  141. func (t *testResolveValidator) Owner(node [32]byte) (addr common.Address, err error) {
  142. return
  143. }
  144. func (t *testResolveValidator) HeaderByNumber(context.Context, *big.Int) (header *types.Header, err error) {
  145. return
  146. }
  147. // TestAPIResolve tests resolving URIs which can either contain content hashes
  148. // or ENS names
  149. func TestAPIResolve(t *testing.T) {
  150. ensAddr := "swarm.eth"
  151. hashAddr := "1111111111111111111111111111111111111111111111111111111111111111"
  152. resolvedAddr := "2222222222222222222222222222222222222222222222222222222222222222"
  153. doesResolve := newTestResolveValidator(resolvedAddr)
  154. doesntResolve := newTestResolveValidator("")
  155. type test struct {
  156. desc string
  157. dns Resolver
  158. addr string
  159. immutable bool
  160. result string
  161. expectErr error
  162. }
  163. tests := []*test{
  164. {
  165. desc: "DNS not configured, hash address, returns hash address",
  166. dns: nil,
  167. addr: hashAddr,
  168. result: hashAddr,
  169. },
  170. {
  171. desc: "DNS not configured, ENS address, returns error",
  172. dns: nil,
  173. addr: ensAddr,
  174. expectErr: errors.New(`no DNS to resolve name: "swarm.eth"`),
  175. },
  176. {
  177. desc: "DNS configured, hash address, hash resolves, returns resolved address",
  178. dns: doesResolve,
  179. addr: hashAddr,
  180. result: resolvedAddr,
  181. },
  182. {
  183. desc: "DNS configured, immutable hash address, hash resolves, returns hash address",
  184. dns: doesResolve,
  185. addr: hashAddr,
  186. immutable: true,
  187. result: hashAddr,
  188. },
  189. {
  190. desc: "DNS configured, hash address, hash doesn't resolve, returns hash address",
  191. dns: doesntResolve,
  192. addr: hashAddr,
  193. result: hashAddr,
  194. },
  195. {
  196. desc: "DNS configured, ENS address, name resolves, returns resolved address",
  197. dns: doesResolve,
  198. addr: ensAddr,
  199. result: resolvedAddr,
  200. },
  201. {
  202. desc: "DNS configured, immutable ENS address, name resolves, returns error",
  203. dns: doesResolve,
  204. addr: ensAddr,
  205. immutable: true,
  206. expectErr: errors.New(`immutable address not a content hash: "swarm.eth"`),
  207. },
  208. {
  209. desc: "DNS configured, ENS address, name doesn't resolve, returns error",
  210. dns: doesntResolve,
  211. addr: ensAddr,
  212. expectErr: errors.New(`DNS name not found: "swarm.eth"`),
  213. },
  214. }
  215. for _, x := range tests {
  216. t.Run(x.desc, func(t *testing.T) {
  217. api := &API{dns: x.dns}
  218. uri := &URI{Addr: x.addr, Scheme: "bzz"}
  219. if x.immutable {
  220. uri.Scheme = "bzz-immutable"
  221. }
  222. res, err := api.ResolveURI(context.TODO(), uri, "")
  223. if err == nil {
  224. if x.expectErr != nil {
  225. t.Fatalf("expected error %q, got result %q", x.expectErr, res)
  226. }
  227. if res.String() != x.result {
  228. t.Fatalf("expected result %q, got %q", x.result, res)
  229. }
  230. } else {
  231. if x.expectErr == nil {
  232. t.Fatalf("expected no error, got %q", err)
  233. }
  234. if err.Error() != x.expectErr.Error() {
  235. t.Fatalf("expected error %q, got %q", x.expectErr, err)
  236. }
  237. }
  238. })
  239. }
  240. }
  241. func TestMultiResolver(t *testing.T) {
  242. doesntResolve := newTestResolveValidator("")
  243. ethAddr := "swarm.eth"
  244. ethHash := "0x2222222222222222222222222222222222222222222222222222222222222222"
  245. ethResolve := newTestResolveValidator(ethHash)
  246. testAddr := "swarm.test"
  247. testHash := "0x1111111111111111111111111111111111111111111111111111111111111111"
  248. testResolve := newTestResolveValidator(testHash)
  249. tests := []struct {
  250. desc string
  251. r Resolver
  252. addr string
  253. result string
  254. err error
  255. }{
  256. {
  257. desc: "No resolvers, returns error",
  258. r: NewMultiResolver(),
  259. err: NewNoResolverError(""),
  260. },
  261. {
  262. desc: "One default resolver, returns resolved address",
  263. r: NewMultiResolver(MultiResolverOptionWithResolver(ethResolve, "")),
  264. addr: ethAddr,
  265. result: ethHash,
  266. },
  267. {
  268. desc: "Two default resolvers, returns resolved address",
  269. r: NewMultiResolver(
  270. MultiResolverOptionWithResolver(ethResolve, ""),
  271. MultiResolverOptionWithResolver(ethResolve, ""),
  272. ),
  273. addr: ethAddr,
  274. result: ethHash,
  275. },
  276. {
  277. desc: "Two default resolvers, first doesn't resolve, returns resolved address",
  278. r: NewMultiResolver(
  279. MultiResolverOptionWithResolver(doesntResolve, ""),
  280. MultiResolverOptionWithResolver(ethResolve, ""),
  281. ),
  282. addr: ethAddr,
  283. result: ethHash,
  284. },
  285. {
  286. desc: "Default resolver doesn't resolve, tld resolver resolve, returns resolved address",
  287. r: NewMultiResolver(
  288. MultiResolverOptionWithResolver(doesntResolve, ""),
  289. MultiResolverOptionWithResolver(ethResolve, "eth"),
  290. ),
  291. addr: ethAddr,
  292. result: ethHash,
  293. },
  294. {
  295. desc: "Three TLD resolvers, third resolves, returns resolved address",
  296. r: NewMultiResolver(
  297. MultiResolverOptionWithResolver(doesntResolve, "eth"),
  298. MultiResolverOptionWithResolver(doesntResolve, "eth"),
  299. MultiResolverOptionWithResolver(ethResolve, "eth"),
  300. ),
  301. addr: ethAddr,
  302. result: ethHash,
  303. },
  304. {
  305. desc: "One TLD resolver doesn't resolve, returns error",
  306. r: NewMultiResolver(
  307. MultiResolverOptionWithResolver(doesntResolve, ""),
  308. MultiResolverOptionWithResolver(ethResolve, "eth"),
  309. ),
  310. addr: ethAddr,
  311. result: ethHash,
  312. },
  313. {
  314. desc: "One defautl and one TLD resolver, all doesn't resolve, returns error",
  315. r: NewMultiResolver(
  316. MultiResolverOptionWithResolver(doesntResolve, ""),
  317. MultiResolverOptionWithResolver(doesntResolve, "eth"),
  318. ),
  319. addr: ethAddr,
  320. result: ethHash,
  321. err: errors.New(`DNS name not found: "swarm.eth"`),
  322. },
  323. {
  324. desc: "Two TLD resolvers, both resolve, returns resolved address",
  325. r: NewMultiResolver(
  326. MultiResolverOptionWithResolver(ethResolve, "eth"),
  327. MultiResolverOptionWithResolver(testResolve, "test"),
  328. ),
  329. addr: testAddr,
  330. result: testHash,
  331. },
  332. {
  333. desc: "One TLD resolver, no default resolver, returns error for different TLD",
  334. r: NewMultiResolver(
  335. MultiResolverOptionWithResolver(ethResolve, "eth"),
  336. ),
  337. addr: testAddr,
  338. err: NewNoResolverError("test"),
  339. },
  340. }
  341. for _, x := range tests {
  342. t.Run(x.desc, func(t *testing.T) {
  343. res, err := x.r.Resolve(x.addr)
  344. if err == nil {
  345. if x.err != nil {
  346. t.Fatalf("expected error %q, got result %q", x.err, res.Hex())
  347. }
  348. if res.Hex() != x.result {
  349. t.Fatalf("expected result %q, got %q", x.result, res.Hex())
  350. }
  351. } else {
  352. if x.err == nil {
  353. t.Fatalf("expected no error, got %q", err)
  354. }
  355. if err.Error() != x.err.Error() {
  356. t.Fatalf("expected error %q, got %q", x.err, err)
  357. }
  358. }
  359. })
  360. }
  361. }
  362. func TestDecryptOriginForbidden(t *testing.T) {
  363. ctx := context.TODO()
  364. ctx = sctx.SetHost(ctx, "swarm-gateways.net")
  365. me := &ManifestEntry{
  366. Access: &AccessEntry{Type: AccessTypePass},
  367. }
  368. api := NewAPI(nil, nil, nil, nil)
  369. f := api.Decryptor(ctx, "")
  370. err := f(me)
  371. if err != ErrDecryptDomainForbidden {
  372. t.Fatalf("should fail with ErrDecryptDomainForbidden, got %v", err)
  373. }
  374. }
  375. func TestDecryptOrigin(t *testing.T) {
  376. for _, v := range []struct {
  377. host string
  378. expectError error
  379. }{
  380. {
  381. host: "localhost",
  382. expectError: ErrDecrypt,
  383. },
  384. {
  385. host: "127.0.0.1",
  386. expectError: ErrDecrypt,
  387. },
  388. {
  389. host: "swarm-gateways.net",
  390. expectError: ErrDecryptDomainForbidden,
  391. },
  392. } {
  393. ctx := context.TODO()
  394. ctx = sctx.SetHost(ctx, v.host)
  395. me := &ManifestEntry{
  396. Access: &AccessEntry{Type: AccessTypePass},
  397. }
  398. api := NewAPI(nil, nil, nil, nil)
  399. f := api.Decryptor(ctx, "")
  400. err := f(me)
  401. if err != v.expectError {
  402. t.Fatalf("should fail with %v, got %v", v.expectError, err)
  403. }
  404. }
  405. }