github.com/klaytn/klaytn@v1.10.2/datasync/chaindatafetcher/kas/repository_test.go (about) 1 package kas 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "math/big" 8 "math/rand" 9 "net/http" 10 "net/http/httptest" 11 "strings" 12 "testing" 13 "time" 14 15 "github.com/stretchr/testify/assert" 16 17 "github.com/jinzhu/gorm" 18 "github.com/klaytn/klaytn/blockchain" 19 "github.com/klaytn/klaytn/blockchain/types" 20 "github.com/klaytn/klaytn/blockchain/vm" 21 "github.com/klaytn/klaytn/common" 22 "github.com/klaytn/klaytn/consensus/gxhash" 23 "github.com/klaytn/klaytn/crypto" 24 "github.com/klaytn/klaytn/crypto/sha3" 25 "github.com/klaytn/klaytn/params" 26 "github.com/klaytn/klaytn/rlp" 27 "github.com/klaytn/klaytn/storage/database" 28 "github.com/stretchr/testify/suite" 29 ) 30 31 var models = []interface{}{ 32 &Tx{}, 33 &FetcherMetadata{}, 34 } 35 36 // configure and generate a test block chain 37 var ( 38 config = params.TestChainConfig 39 gendb = database.NewMemoryDBManager() 40 key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") 41 address = crypto.PubkeyToAddress(key.PublicKey) 42 funds = big.NewInt(100000000000000000) 43 testGenesis = &blockchain.Genesis{ 44 Config: config, 45 Alloc: blockchain.GenesisAlloc{address: {Balance: funds}}, 46 } 47 genesis = testGenesis.MustCommit(gendb) 48 signer = types.LatestSignerForChainID(config.ChainID) 49 ) 50 51 type SuiteRepository struct { 52 suite.Suite 53 repo *repository 54 } 55 56 func genRandomAddress() *common.Address { 57 key, _ := crypto.GenerateKey() 58 addr := crypto.PubkeyToAddress(key.PublicKey) 59 return &addr 60 } 61 62 func genRandomHash() (h common.Hash) { 63 hasher := sha3.NewKeccak256() 64 65 r := rand.Uint64() 66 rlp.Encode(hasher, r) 67 hasher.Sum(h[:0]) 68 69 return h 70 } 71 72 func makeChainEventsWithInternalTraces(numBlocks int, genTxs func(i int, block *blockchain.BlockGen)) ([]blockchain.ChainEvent, error) { 73 db := database.NewMemoryDBManager() 74 testGenesis.MustCommit(db) 75 76 // create new blockchain with enabled internal tx tracing option 77 b, _ := blockchain.NewBlockChain(db, nil, testGenesis.Config, gxhash.NewFaker(), vm.Config{Debug: true, EnableInternalTxTracing: true}) 78 defer b.Stop() 79 80 // subscribe a new chain event channel 81 chainEventCh := make(chan blockchain.ChainEvent, numBlocks) 82 subscription := b.SubscribeChainEvent(chainEventCh) 83 defer subscription.Unsubscribe() 84 85 // generate blocks 86 blocks, _ := blockchain.GenerateChain(testGenesis.Config, genesis, gxhash.NewFaker(), gendb, numBlocks, genTxs) 87 88 // insert the generated blocks into the test chain 89 if _, err := b.InsertChain(blocks); err != nil { 90 return nil, err 91 } 92 93 var events []blockchain.ChainEvent 94 for i := 0; i < numBlocks; i++ { 95 timer := time.NewTimer(1 * time.Second) 96 select { 97 case <-timer.C: 98 return nil, fmt.Errorf("timeout. too late receive a chain event: %v block", i) 99 case ev := <-chainEventCh: 100 events = append(events, ev) 101 } 102 timer.Stop() 103 } 104 105 return events, nil 106 } 107 108 func setTestDatabase(t *testing.T, mysql *gorm.DB) { 109 // Drop previous test database if possible. 110 if err := mysql.Exec("DROP DATABASE IF EXISTS test").Error; err != nil { 111 if !strings.Contains(err.Error(), "database doesn't exist") { 112 t.Fatal("Unexpected error happened!", "err", err) 113 } 114 } 115 // Create new test database. 116 if err := mysql.Exec("CREATE DATABASE test DEFAULT CHARACTER SET UTF8").Error; err != nil { 117 t.Fatal("Error while creating test database", "err", err) 118 } 119 // Use test database 120 if err := mysql.Exec("USE test").Error; err != nil { 121 t.Fatal("Error while setting test database", "err", err) 122 } 123 124 // Auto-migrate data model from model.DataModels 125 if err := mysql.AutoMigrate(models...).Error; err != nil { 126 t.Fatal("Error while auto migrating data models", "err", err) 127 } 128 } 129 130 func (s *SuiteRepository) SetupSuite() { 131 id := "root" 132 133 mysql, err := gorm.Open("mysql", fmt.Sprintf("%s@/?parseTime=True", id)) 134 if err != nil { 135 s.T().Log("Failed connecting to mysql", "id", id, "err", err) 136 s.T().Skip() 137 } 138 139 setTestDatabase(s.T(), mysql) 140 s.repo = &repository{db: mysql, config: DefaultKASConfig} 141 } 142 143 func TestSuite(t *testing.T) { 144 suite.Run(t, new(SuiteRepository)) 145 } 146 147 func Test_repository_InvalidateCacheEOAList(t *testing.T) { 148 testXChainId := "test-xkrn" 149 testAuth := "test-auth" 150 testEOAs := make(map[common.Address]struct{}) 151 numEOAs := 10 152 for i := 0; i < numEOAs; i++ { 153 testEOAs[*genRandomAddress()] = struct{}{} 154 } 155 156 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { 157 assert.Equal(t, testXChainId, req.Header.Get("x-chain-id")) 158 assert.Equal(t, makeBasicAuthWithParam(testAuth), req.Header.Get("Authorization")) 159 160 buffer := make([]byte, 1024) 161 bodyStr := "" 162 163 for { 164 n, err := req.Body.Read(buffer) 165 bodyStr += string(buffer[:n]) 166 if err == io.EOF { 167 break 168 } 169 } 170 171 var body map[string]interface{} 172 173 assert.NoError(t, json.Unmarshal([]byte(bodyStr), &body)) 174 payload := body["payload"].(map[string]interface{}) 175 eoaList := payload["addresses"].([]string) 176 for _, eoa := range eoaList { 177 _, ok := testEOAs[common.HexToAddress(eoa)] 178 assert.True(t, ok) 179 } 180 w.WriteHeader(http.StatusOK) 181 w.Write([]byte("this is test result")) 182 })) 183 defer server.Close() 184 185 r := &repository{ 186 config: &KASConfig{ 187 XChainId: testXChainId, 188 BasicAuthParam: testAuth, 189 CacheInvalidationURL: server.URL, 190 }, 191 } 192 193 r.InvalidateCacheEOAList(testEOAs) 194 }