github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/pkg/names/custom_integration_test.go (about) 1 package names 2 3 import ( 4 "encoding/csv" 5 "errors" 6 "fmt" 7 "io" 8 "os" 9 "path/filepath" 10 "testing" 11 12 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base" 13 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/types" 14 "github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/utils" 15 ) 16 17 func TestCrudIntegration(t *testing.T) { 18 chain := utils.GetTestChain() 19 tmpDirPath := filepath.Join(os.TempDir(), "trueblocks") 20 if err := os.MkdirAll(tmpDirPath, 0777); err != nil { 21 t.Fatal(err) 22 } 23 defer func() { 24 if err := os.RemoveAll(tmpDirPath); err != nil { 25 t.Fatal("os.RemoveAll:", err) 26 } 27 }() 28 loadTestDatabase := func() *os.File { 29 tempFile, err := os.OpenFile( 30 filepath.Join(os.TempDir(), "trueblocks", "names_custom.tab"), 31 os.O_RDWR|os.O_CREATE|os.O_TRUNC, 32 0777, 33 ) 34 if err != nil { 35 t.Fatal(err) 36 } 37 return tempFile 38 } 39 tempFile := loadTestDatabase() 40 customNames = map[base.Address]types.Name{} 41 addrStr := "0x1f9090aae28b8a3dceadf281b0f12828e676c326" 42 addr := base.HexToAddress(addrStr) 43 expected := types.Name{ 44 Name: "test name", 45 Address: addr, 46 } 47 48 expected.IsCustom = true 49 customNamesMutex.Lock() 50 customNames[expected.Address] = expected 51 customNamesMutex.Unlock() 52 if err := writeCustomNames(tempFile); err != nil { 53 t.Fatal(err) 54 } 55 56 tempFile.Seek(0, 0) 57 r := csv.NewReader(tempFile) 58 r.Comma = '\t' 59 60 result, err := r.ReadAll() 61 if err != nil { 62 t.Fatal(err) 63 } 64 65 if value := result[1][1]; value != expected.Address.Hex() { 66 t.Fatal("create: wrong address", value) 67 } 68 if value := result[1][2]; value != expected.Name { 69 t.Fatal("create: wrong name", value) 70 } 71 72 // Read 73 read := ReadName(DatabaseCustom, chain, addr) 74 75 if value := read.Address; value != expected.Address { 76 t.Fatal("read: wrong address", value) 77 } 78 if value := read.Name; value != expected.Name { 79 t.Fatal("read: wrong name", value) 80 } 81 82 // Update 83 updated, err := setIfExists(tempFile, &types.Name{ 84 Name: "new name", 85 Address: addr, 86 }) 87 if err != nil { 88 t.Fatal("update:", err) 89 } 90 if name := updated.Name; name != "new name" { 91 t.Fatal("wrong name", name) 92 } 93 if addr := updated.Address.Hex(); addr != addrStr { 94 t.Fatal("wrong address", addr) 95 } 96 97 // Delete 98 deleted, err := changeDeleted(tempFile, addr, true) 99 if err != nil { 100 t.Fatal("delete:", err) 101 } 102 if deleted == nil { 103 t.Fatal("delete: returned name is nil") 104 } 105 if !deleted.Deleted { 106 t.Fatal("delete: delete flag not set") 107 } 108 109 // Undelete 110 undeleted, err := changeDeleted(tempFile, addr, false) 111 if err != nil { 112 t.Fatal("undelete:", err) 113 } 114 if undeleted == nil { 115 t.Fatal("undelete: returned name is nil") 116 } 117 if undeleted.Deleted { 118 t.Fatal("undelete: delete flag not unset") 119 } 120 121 // Invalid remove 122 // Commented out, because C++ doesn't check it 123 // _, err = names.RemoveName(names.DatabaseCustom, tempFile, addr) 124 // if err == nil { 125 // t.Fatal("remove: expected error") 126 // } 127 128 // Remove 129 // Set flag first 130 _, err = changeDeleted(tempFile, addr, true) 131 if err != nil { 132 t.Fatal("remove: delete:", err) 133 } 134 removed, err := removeIfExists(tempFile, addr) 135 if err != nil { 136 t.Fatal("remove:", err) 137 } 138 if name := removed.Name; name != "new name" { 139 t.Fatal("remove: wrong name", name) 140 } 141 if addr := removed.Address.Hex(); addr != addrStr { 142 t.Fatal("remove: wrong address", addr) 143 } 144 145 // Check what was written to the file 146 tempFile = loadTestDatabase() 147 testDb, err := unmarshallCustomNames(tempFile, nil, types.Custom, &map[base.Address]types.Name{}) 148 if err != nil && !errors.Is(err, io.EOF) { 149 t.Fatal("remove: unmarshallCustomNames:", err) 150 } 151 if _, ok := testDb[addr]; ok { 152 t.Fatal("record was removed, but it is still present") 153 } 154 } 155 156 func setIfExists(output *os.File, name *types.Name) (result *types.Name, err error) { 157 if _, ok := customNames[name.Address]; !ok { 158 return nil, fmt.Errorf("no custom name for address %s", name.Address.Hex()) 159 } 160 161 name.IsCustom = true 162 customNamesMutex.Lock() 163 defer customNamesMutex.Unlock() 164 customNames[name.Address] = *name 165 return name, writeCustomNames(output) 166 } 167 168 func removeIfExists(output *os.File, address base.Address) (name *types.Name, err error) { 169 found, ok := customNames[address] 170 if !ok { 171 return nil, fmt.Errorf("no custom name for address %s", address.Hex()) 172 } 173 customNamesMutex.Lock() 174 defer customNamesMutex.Unlock() 175 176 delete(customNames, address) 177 return &found, writeCustomNames(output) 178 }