api_test.go 11 KB

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