github.com/jeffallen/go-ethereum@v1.1.4-0.20150910155051-571d3236c49c/common/natspec/natspec_e2e_test.go.orig (about) 1 package natspec 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "strings" 8 "testing" 9 10 "github.com/ethereum/go-ethereum/accounts" 11 "github.com/ethereum/go-ethereum/common" 12 "github.com/ethereum/go-ethereum/common/docserver" 13 "github.com/ethereum/go-ethereum/common/registrar" 14 "github.com/ethereum/go-ethereum/core" 15 "github.com/ethereum/go-ethereum/core/state" 16 "github.com/ethereum/go-ethereum/crypto" 17 "github.com/ethereum/go-ethereum/eth" 18 xe "github.com/ethereum/go-ethereum/xeth" 19 ) 20 21 const ( 22 testBalance = "10000000000000000000" 23 24 testFileName = "long_file_name_for_testing_registration_of_URLs_longer_than_32_bytes.content" 25 26 testNotice = "Register key `utils.toHex(_key)` <- content `utils.toHex(_content)`" 27 28 testExpNotice = "Register key 0xadd1a7d961cff0242089674ec2ef6fca671ab15e1fe80e38859fc815b98d88ab <- content 0xb3a2dea218de5d8bbe6c4645aadbf67b5ab00ecb1a9ec95dbdad6a0eed3e41a7" 29 30 testExpNotice2 = `About to submit transaction (NatSpec notice error: abi key does not match any method): {"params":[{"to":"%s","data": "0x31e12c20"}]}` 31 32 testExpNotice3 = `About to submit transaction (no NatSpec info found for contract: content hash not found for '0x1392c62d05b2d149e22a339c531157ae06b44d39a674cce500064b12b9aeb019'): {"params":[{"to":"%s","data": "0x300a3bbfb3a2dea218de5d8bbe6c4645aadbf67b5ab00ecb1a9ec95dbdad6a0eed3e41a7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066696c653a2f2f2f746573742e636f6e74656e74"}]}` 33 ) 34 35 const ( 36 testUserDoc = ` 37 { 38 "methods": { 39 "register(uint256,uint256)": { 40 "notice": "` + testNotice + `" 41 } 42 }, 43 "invariants": [ 44 { "notice": "" } 45 ], 46 "construction": [ 47 { "notice": "" } 48 ] 49 } 50 ` 51 testAbiDefinition = ` 52 [{ 53 "name": "register", 54 "constant": false, 55 "type": "function", 56 "inputs": [{ 57 "name": "_key", 58 "type": "uint256" 59 }, { 60 "name": "_content", 61 "type": "uint256" 62 }], 63 "outputs": [] 64 }] 65 ` 66 67 testContractInfo = ` 68 { 69 "userDoc": ` + testUserDoc + `, 70 "abiDefinition": ` + testAbiDefinition + ` 71 } 72 ` 73 ) 74 75 type testFrontend struct { 76 t *testing.T 77 ethereum *eth.Ethereum 78 xeth *xe.XEth 79 coinbase common.Address 80 stateDb *state.StateDB 81 txc uint64 82 lastConfirm string 83 wantNatSpec bool 84 } 85 86 func (self *testFrontend) UnlockAccount(acc []byte) bool { 87 self.ethereum.AccountManager().Unlock(common.BytesToAddress(acc), "password") 88 return true 89 } 90 91 func (self *testFrontend) ConfirmTransaction(tx string) bool { 92 if self.wantNatSpec { 93 ds := docserver.New("/tmp/") 94 self.lastConfirm = GetNotice(self.xeth, tx, ds) 95 } 96 return true 97 } 98 99 func testEth(t *testing.T) (ethereum *eth.Ethereum, err error) { 100 101 os.RemoveAll("/tmp/eth-natspec/") 102 103 err = os.MkdirAll("/tmp/eth-natspec/keystore", os.ModePerm) 104 if err != nil { 105 panic(err) 106 } 107 108 // create a testAddress 109 ks := crypto.NewKeyStorePassphrase("/tmp/eth-natspec/keystore") 110 am := accounts.NewManager(ks) 111 testAccount, err := am.NewAccount("password") 112 if err != nil { 113 panic(err) 114 } 115 testAddress := strings.TrimPrefix(testAccount.Address.Hex(), "0x") 116 117 // set up mock genesis with balance on the testAddress 118 core.GenesisAccounts = []byte(`{ 119 "` + testAddress + `": {"balance": "` + testBalance + `"} 120 }`) 121 122 // only use minimalistic stack with no networking 123 ethereum, err = eth.New(ð.Config{ 124 DataDir: "/tmp/eth-natspec", 125 AccountManager: am, 126 MaxPeers: 0, 127 }) 128 129 if err != nil { 130 panic(err) 131 } 132 133 return 134 } 135 136 func testInit(t *testing.T) (self *testFrontend) { 137 // initialise and start minimal ethereum stack 138 ethereum, err := testEth(t) 139 if err != nil { 140 t.Errorf("error creating ethereum: %v", err) 141 return 142 } 143 err = ethereum.Start() 144 if err != nil { 145 t.Errorf("error starting ethereum: %v", err) 146 return 147 } 148 149 // mock frontend 150 self = &testFrontend{t: t, ethereum: ethereum} 151 self.xeth = xe.New(ethereum, self) 152 153 addr, _ := ethereum.Etherbase() 154 self.coinbase = addr 155 self.stateDb = self.ethereum.ChainManager().State().Copy() 156 157 // initialise the registry contracts 158 reg := registrar.New(self.xeth) 159 err = reg.SetHashReg("", addr) 160 if err != nil { 161 t.Errorf("error creating HashReg: %v", err) 162 } 163 err = reg.SetUrlHint("", addr) 164 if err != nil { 165 t.Errorf("error creating UrlHint: %v", err) 166 } 167 self.applyTxs() 168 169 return 170 171 } 172 173 // this is needed for transaction to be applied to the state in testing 174 // the heavy lifing is done in XEth.ApplyTestTxs 175 // this is fragile, 176 // and does process leaking since xeth loops cannot quit safely 177 // should be replaced by proper mining with testDAG for easy full integration tests 178 func (self *testFrontend) applyTxs() { 179 self.txc, self.xeth = self.xeth.ApplyTestTxs(self.stateDb, self.coinbase, self.txc) 180 return 181 } 182 183 // end to end test 184 func TestNatspecE2E(t *testing.T) { 185 t.Skip() 186 187 tf := testInit(t) 188 defer tf.ethereum.Stop() 189 190 // create a contractInfo file (mock cloud-deployed contract metadocs) 191 // incidentally this is the info for the registry contract itself 192 ioutil.WriteFile("/tmp/"+testFileName, []byte(testContractInfo), os.ModePerm) 193 dochash := common.BytesToHash(crypto.Sha3([]byte(testContractInfo))) 194 195 // take the codehash for the contract we wanna test 196 // codehex := tf.xeth.CodeAt(registar.HashRegAddr) 197 codeb := tf.xeth.CodeAtBytes(registrar.HashRegAddr) 198 codehash := common.BytesToHash(crypto.Sha3(codeb)) 199 200 // use resolver to register codehash->dochash->url 201 // test if globalregistry works 202 // registrar.HashRefAddr = "0x0" 203 // registrar.UrlHintAddr = "0x0" 204 reg := registrar.New(tf.xeth) 205 _, err := reg.SetHashToHash(tf.coinbase, codehash, dochash) 206 if err != nil { 207 t.Errorf("error registering: %v", err) 208 } 209 _, err = reg.SetUrlToHash(tf.coinbase, dochash, "file:///"+testFileName) 210 if err != nil { 211 t.Errorf("error registering: %v", err) 212 } 213 // apply txs to the state 214 tf.applyTxs() 215 216 // NatSpec info for register method of HashReg contract installed 217 // now using the same transactions to check confirm messages 218 219 tf.wantNatSpec = true // this is set so now the backend uses natspec confirmation 220 _, err = reg.SetHashToHash(tf.coinbase, codehash, dochash) 221 if err != nil { 222 t.Errorf("error calling contract registry: %v", err) 223 } 224 225 fmt.Printf("GlobalRegistrar: %v, HashReg: %v, UrlHint: %v\n", registrar.GlobalRegistrarAddr, registrar.HashRegAddr, registrar.UrlHintAddr) 226 if tf.lastConfirm != testExpNotice { 227 t.Errorf("Wrong confirm message. expected '%v', got '%v'", testExpNotice, tf.lastConfirm) 228 } 229 230 // test unknown method 231 exp := fmt.Sprintf(testExpNotice2, registrar.HashRegAddr) 232 _, err = reg.SetOwner(tf.coinbase) 233 if err != nil { 234 t.Errorf("error setting owner: %v", err) 235 } 236 237 if tf.lastConfirm != exp { 238 t.Errorf("Wrong confirm message, expected '%v', got '%v'", exp, tf.lastConfirm) 239 } 240 241 // test unknown contract 242 exp = fmt.Sprintf(testExpNotice3, registrar.UrlHintAddr) 243 244 _, err = reg.SetUrlToHash(tf.coinbase, dochash, "file:///test.content") 245 if err != nil { 246 t.Errorf("error registering: %v", err) 247 } 248 249 if tf.lastConfirm != exp { 250 t.Errorf("Wrong confirm message, expected '%v', got '%v'", exp, tf.lastConfirm) 251 } 252 253 }