export_test.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // Copyright 2021 The go-ethereum Authors
  2. // This file is part of go-ethereum.
  3. //
  4. // go-ethereum is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU 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. // go-ethereum 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 General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License
  15. // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
  16. package utils
  17. import (
  18. "fmt"
  19. "os"
  20. "strings"
  21. "testing"
  22. "time"
  23. "github.com/ethereum/go-ethereum/core/rawdb"
  24. "github.com/ethereum/go-ethereum/rlp"
  25. )
  26. // TestExport does basic sanity checks on the export/import functionality
  27. func TestExport(t *testing.T) {
  28. f := fmt.Sprintf("%v/tempdump", os.TempDir())
  29. defer func() {
  30. os.Remove(f)
  31. }()
  32. testExport(t, f)
  33. }
  34. func TestExportGzip(t *testing.T) {
  35. f := fmt.Sprintf("%v/tempdump.gz", os.TempDir())
  36. defer func() {
  37. os.Remove(f)
  38. }()
  39. testExport(t, f)
  40. }
  41. type testIterator struct {
  42. index int
  43. }
  44. func newTestIterator() *testIterator {
  45. return &testIterator{index: -1}
  46. }
  47. func (iter *testIterator) Next() (byte, []byte, []byte, bool) {
  48. if iter.index >= 999 {
  49. return 0, nil, nil, false
  50. }
  51. iter.index += 1
  52. if iter.index == 42 {
  53. iter.index += 1
  54. }
  55. return OpBatchAdd, []byte(fmt.Sprintf("key-%04d", iter.index)),
  56. []byte(fmt.Sprintf("value %d", iter.index)), true
  57. }
  58. func (iter *testIterator) Release() {}
  59. func testExport(t *testing.T, f string) {
  60. err := ExportChaindata(f, "testdata", newTestIterator(), make(chan struct{}))
  61. if err != nil {
  62. t.Fatal(err)
  63. }
  64. db := rawdb.NewMemoryDatabase()
  65. err = ImportLDBData(db, f, 5, make(chan struct{}))
  66. if err != nil {
  67. t.Fatal(err)
  68. }
  69. // verify
  70. for i := 0; i < 1000; i++ {
  71. v, err := db.Get([]byte(fmt.Sprintf("key-%04d", i)))
  72. if (i < 5 || i == 42) && err == nil {
  73. t.Fatalf("expected no element at idx %d, got '%v'", i, string(v))
  74. }
  75. if !(i < 5 || i == 42) {
  76. if err != nil {
  77. t.Fatalf("expected element idx %d: %v", i, err)
  78. }
  79. if have, want := string(v), fmt.Sprintf("value %d", i); have != want {
  80. t.Fatalf("have %v, want %v", have, want)
  81. }
  82. }
  83. }
  84. v, err := db.Get([]byte(fmt.Sprintf("key-%04d", 1000)))
  85. if err == nil {
  86. t.Fatalf("expected no element at idx %d, got '%v'", 1000, string(v))
  87. }
  88. }
  89. // testDeletion tests if the deletion markers can be exported/imported correctly
  90. func TestDeletionExport(t *testing.T) {
  91. f := fmt.Sprintf("%v/tempdump", os.TempDir())
  92. defer func() {
  93. os.Remove(f)
  94. }()
  95. testDeletion(t, f)
  96. }
  97. // TestDeletionExportGzip tests if the deletion markers can be exported/imported
  98. // correctly with gz compression.
  99. func TestDeletionExportGzip(t *testing.T) {
  100. f := fmt.Sprintf("%v/tempdump.gz", os.TempDir())
  101. defer func() {
  102. os.Remove(f)
  103. }()
  104. testDeletion(t, f)
  105. }
  106. type deletionIterator struct {
  107. index int
  108. }
  109. func newDeletionIterator() *deletionIterator {
  110. return &deletionIterator{index: -1}
  111. }
  112. func (iter *deletionIterator) Next() (byte, []byte, []byte, bool) {
  113. if iter.index >= 999 {
  114. return 0, nil, nil, false
  115. }
  116. iter.index += 1
  117. if iter.index == 42 {
  118. iter.index += 1
  119. }
  120. return OpBatchDel, []byte(fmt.Sprintf("key-%04d", iter.index)), nil, true
  121. }
  122. func (iter *deletionIterator) Release() {}
  123. func testDeletion(t *testing.T, f string) {
  124. err := ExportChaindata(f, "testdata", newDeletionIterator(), make(chan struct{}))
  125. if err != nil {
  126. t.Fatal(err)
  127. }
  128. db := rawdb.NewMemoryDatabase()
  129. for i := 0; i < 1000; i++ {
  130. db.Put([]byte(fmt.Sprintf("key-%04d", i)), []byte(fmt.Sprintf("value %d", i)))
  131. }
  132. err = ImportLDBData(db, f, 5, make(chan struct{}))
  133. if err != nil {
  134. t.Fatal(err)
  135. }
  136. for i := 0; i < 1000; i++ {
  137. v, err := db.Get([]byte(fmt.Sprintf("key-%04d", i)))
  138. if i < 5 || i == 42 {
  139. if err != nil {
  140. t.Fatalf("expected element at idx %d, got '%v'", i, err)
  141. }
  142. if have, want := string(v), fmt.Sprintf("value %d", i); have != want {
  143. t.Fatalf("have %v, want %v", have, want)
  144. }
  145. }
  146. if !(i < 5 || i == 42) {
  147. if err == nil {
  148. t.Fatalf("expected no element idx %d: %v", i, string(v))
  149. }
  150. }
  151. }
  152. }
  153. // TestImportFutureFormat tests that we reject unsupported future versions.
  154. func TestImportFutureFormat(t *testing.T) {
  155. f := fmt.Sprintf("%v/tempdump-future", os.TempDir())
  156. defer func() {
  157. os.Remove(f)
  158. }()
  159. fh, err := os.OpenFile(f, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
  160. if err != nil {
  161. t.Fatal(err)
  162. }
  163. defer fh.Close()
  164. if err := rlp.Encode(fh, &exportHeader{
  165. Magic: exportMagic,
  166. Version: 500,
  167. Kind: "testdata",
  168. UnixTime: uint64(time.Now().Unix()),
  169. }); err != nil {
  170. t.Fatal(err)
  171. }
  172. db2 := rawdb.NewMemoryDatabase()
  173. err = ImportLDBData(db2, f, 0, make(chan struct{}))
  174. if err == nil {
  175. t.Fatal("Expected error, got none")
  176. }
  177. if !strings.HasPrefix(err.Error(), "incompatible version") {
  178. t.Fatalf("wrong error: %v", err)
  179. }
  180. }