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(&eth.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  }