api_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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(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. // exp := expResponse([]byte(content), "text/plain", 0)
  103. addr, wait, err := api.Put(content, exp.MimeType, toEncrypt)
  104. if err != nil {
  105. t.Fatalf("unexpected error: %v", err)
  106. }
  107. wait()
  108. resp := testGet(t, api, addr.Hex(), "")
  109. checkResponse(t, resp, exp)
  110. })
  111. }
  112. // testResolver implements the Resolver interface and either returns the given
  113. // hash if it is set, or returns a "name not found" error
  114. type testResolveValidator struct {
  115. hash *common.Hash
  116. }
  117. func newTestResolveValidator(addr string) *testResolveValidator {
  118. r := &testResolveValidator{}
  119. if addr != "" {
  120. hash := common.HexToHash(addr)
  121. r.hash = &hash
  122. }
  123. return r
  124. }
  125. func (t *testResolveValidator) Resolve(addr string) (common.Hash, error) {
  126. if t.hash == nil {
  127. return common.Hash{}, fmt.Errorf("DNS name not found: %q", addr)
  128. }
  129. return *t.hash, nil
  130. }
  131. func (t *testResolveValidator) Owner(node [32]byte) (addr common.Address, err error) {
  132. return
  133. }
  134. func (t *testResolveValidator) HeaderByNumber(context.Context, *big.Int) (header *types.Header, err error) {
  135. return
  136. }
  137. // TestAPIResolve tests resolving URIs which can either contain content hashes
  138. // or ENS names
  139. func TestAPIResolve(t *testing.T) {
  140. ensAddr := "swarm.eth"
  141. hashAddr := "1111111111111111111111111111111111111111111111111111111111111111"
  142. resolvedAddr := "2222222222222222222222222222222222222222222222222222222222222222"
  143. doesResolve := newTestResolveValidator(resolvedAddr)
  144. doesntResolve := newTestResolveValidator("")
  145. type test struct {
  146. desc string
  147. dns Resolver
  148. addr string
  149. immutable bool
  150. result string
  151. expectErr error
  152. }
  153. tests := []*test{
  154. {
  155. desc: "DNS not configured, hash address, returns hash address",
  156. dns: nil,
  157. addr: hashAddr,
  158. result: hashAddr,
  159. },
  160. {
  161. desc: "DNS not configured, ENS address, returns error",
  162. dns: nil,
  163. addr: ensAddr,
  164. expectErr: errors.New(`no DNS to resolve name: "swarm.eth"`),
  165. },
  166. {
  167. desc: "DNS configured, hash address, hash resolves, returns resolved address",
  168. dns: doesResolve,
  169. addr: hashAddr,
  170. result: resolvedAddr,
  171. },
  172. {
  173. desc: "DNS configured, immutable hash address, hash resolves, returns hash address",
  174. dns: doesResolve,
  175. addr: hashAddr,
  176. immutable: true,
  177. result: hashAddr,
  178. },
  179. {
  180. desc: "DNS configured, hash address, hash doesn't resolve, returns hash address",
  181. dns: doesntResolve,
  182. addr: hashAddr,
  183. result: hashAddr,
  184. },
  185. {
  186. desc: "DNS configured, ENS address, name resolves, returns resolved address",
  187. dns: doesResolve,
  188. addr: ensAddr,
  189. result: resolvedAddr,
  190. },
  191. {
  192. desc: "DNS configured, immutable ENS address, name resolves, returns error",
  193. dns: doesResolve,
  194. addr: ensAddr,
  195. immutable: true,
  196. expectErr: errors.New(`immutable address not a content hash: "swarm.eth"`),
  197. },
  198. {
  199. desc: "DNS configured, ENS address, name doesn't resolve, returns error",
  200. dns: doesntResolve,
  201. addr: ensAddr,
  202. expectErr: errors.New(`DNS name not found: "swarm.eth"`),
  203. },
  204. }
  205. for _, x := range tests {
  206. t.Run(x.desc, func(t *testing.T) {
  207. api := &API{dns: x.dns}
  208. uri := &URI{Addr: x.addr, Scheme: "bzz"}
  209. if x.immutable {
  210. uri.Scheme = "bzz-immutable"
  211. }
  212. res, err := api.Resolve(uri)
  213. if err == nil {
  214. if x.expectErr != nil {
  215. t.Fatalf("expected error %q, got result %q", x.expectErr, res)
  216. }
  217. if res.String() != x.result {
  218. t.Fatalf("expected result %q, got %q", x.result, res)
  219. }
  220. } else {
  221. if x.expectErr == nil {
  222. t.Fatalf("expected no error, got %q", err)
  223. }
  224. if err.Error() != x.expectErr.Error() {
  225. t.Fatalf("expected error %q, got %q", x.expectErr, err)
  226. }
  227. }
  228. })
  229. }
  230. }
  231. func TestMultiResolver(t *testing.T) {
  232. doesntResolve := newTestResolveValidator("")
  233. ethAddr := "swarm.eth"
  234. ethHash := "0x2222222222222222222222222222222222222222222222222222222222222222"
  235. ethResolve := newTestResolveValidator(ethHash)
  236. testAddr := "swarm.test"
  237. testHash := "0x1111111111111111111111111111111111111111111111111111111111111111"
  238. testResolve := newTestResolveValidator(testHash)
  239. tests := []struct {
  240. desc string
  241. r Resolver
  242. addr string
  243. result string
  244. err error
  245. }{
  246. {
  247. desc: "No resolvers, returns error",
  248. r: NewMultiResolver(),
  249. err: NewNoResolverError(""),
  250. },
  251. {
  252. desc: "One default resolver, returns resolved address",
  253. r: NewMultiResolver(MultiResolverOptionWithResolver(ethResolve, "")),
  254. addr: ethAddr,
  255. result: ethHash,
  256. },
  257. {
  258. desc: "Two default resolvers, returns resolved address",
  259. r: NewMultiResolver(
  260. MultiResolverOptionWithResolver(ethResolve, ""),
  261. MultiResolverOptionWithResolver(ethResolve, ""),
  262. ),
  263. addr: ethAddr,
  264. result: ethHash,
  265. },
  266. {
  267. desc: "Two default resolvers, first doesn't resolve, returns resolved address",
  268. r: NewMultiResolver(
  269. MultiResolverOptionWithResolver(doesntResolve, ""),
  270. MultiResolverOptionWithResolver(ethResolve, ""),
  271. ),
  272. addr: ethAddr,
  273. result: ethHash,
  274. },
  275. {
  276. desc: "Default resolver doesn't resolve, tld resolver resolve, returns resolved address",
  277. r: NewMultiResolver(
  278. MultiResolverOptionWithResolver(doesntResolve, ""),
  279. MultiResolverOptionWithResolver(ethResolve, "eth"),
  280. ),
  281. addr: ethAddr,
  282. result: ethHash,
  283. },
  284. {
  285. desc: "Three TLD resolvers, third resolves, returns resolved address",
  286. r: NewMultiResolver(
  287. MultiResolverOptionWithResolver(doesntResolve, "eth"),
  288. MultiResolverOptionWithResolver(doesntResolve, "eth"),
  289. MultiResolverOptionWithResolver(ethResolve, "eth"),
  290. ),
  291. addr: ethAddr,
  292. result: ethHash,
  293. },
  294. {
  295. desc: "One TLD resolver doesn't resolve, returns error",
  296. r: NewMultiResolver(
  297. MultiResolverOptionWithResolver(doesntResolve, ""),
  298. MultiResolverOptionWithResolver(ethResolve, "eth"),
  299. ),
  300. addr: ethAddr,
  301. result: ethHash,
  302. },
  303. {
  304. desc: "One defautl and one TLD resolver, all doesn't resolve, returns error",
  305. r: NewMultiResolver(
  306. MultiResolverOptionWithResolver(doesntResolve, ""),
  307. MultiResolverOptionWithResolver(doesntResolve, "eth"),
  308. ),
  309. addr: ethAddr,
  310. result: ethHash,
  311. err: errors.New(`DNS name not found: "swarm.eth"`),
  312. },
  313. {
  314. desc: "Two TLD resolvers, both resolve, returns resolved address",
  315. r: NewMultiResolver(
  316. MultiResolverOptionWithResolver(ethResolve, "eth"),
  317. MultiResolverOptionWithResolver(testResolve, "test"),
  318. ),
  319. addr: testAddr,
  320. result: testHash,
  321. },
  322. {
  323. desc: "One TLD resolver, no default resolver, returns error for different TLD",
  324. r: NewMultiResolver(
  325. MultiResolverOptionWithResolver(ethResolve, "eth"),
  326. ),
  327. addr: testAddr,
  328. err: NewNoResolverError("test"),
  329. },
  330. }
  331. for _, x := range tests {
  332. t.Run(x.desc, func(t *testing.T) {
  333. res, err := x.r.Resolve(x.addr)
  334. if err == nil {
  335. if x.err != nil {
  336. t.Fatalf("expected error %q, got result %q", x.err, res.Hex())
  337. }
  338. if res.Hex() != x.result {
  339. t.Fatalf("expected result %q, got %q", x.result, res.Hex())
  340. }
  341. } else {
  342. if x.err == nil {
  343. t.Fatalf("expected no error, got %q", err)
  344. }
  345. if err.Error() != x.err.Error() {
  346. t.Fatalf("expected error %q, got %q", x.err, err)
  347. }
  348. }
  349. })
  350. }
  351. }