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