blocktestcmd.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // Copyright 2015 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. package main
  17. import (
  18. "fmt"
  19. "os"
  20. "github.com/codegangsta/cli"
  21. "github.com/ethereum/go-ethereum/cmd/utils"
  22. "github.com/ethereum/go-ethereum/eth"
  23. "github.com/ethereum/go-ethereum/ethdb"
  24. "github.com/ethereum/go-ethereum/tests"
  25. )
  26. var blocktestCommand = cli.Command{
  27. Action: runBlockTest,
  28. Name: "blocktest",
  29. Usage: `loads a block test file`,
  30. Description: `
  31. The first argument should be a block test file.
  32. The second argument is the name of a block test from the file.
  33. The block test will be loaded into an in-memory database.
  34. If loading succeeds, the RPC server is started. Clients will
  35. be able to interact with the chain defined by the test.
  36. `,
  37. }
  38. func runBlockTest(ctx *cli.Context) {
  39. var (
  40. file, testname string
  41. rpc bool
  42. )
  43. args := ctx.Args()
  44. switch {
  45. case len(args) == 1:
  46. file = args[0]
  47. case len(args) == 2:
  48. file, testname = args[0], args[1]
  49. case len(args) == 3:
  50. file, testname = args[0], args[1]
  51. rpc = true
  52. default:
  53. utils.Fatalf(`Usage: ethereum blocktest <path-to-test-file> [ <test-name> [ "rpc" ] ]`)
  54. }
  55. bt, err := tests.LoadBlockTests(file)
  56. if err != nil {
  57. utils.Fatalf("%v", err)
  58. }
  59. // run all tests if no test name is specified
  60. if testname == "" {
  61. ecode := 0
  62. for name, test := range bt {
  63. fmt.Printf("----------------- Running Block Test %q\n", name)
  64. ethereum, err := runOneBlockTest(ctx, test)
  65. if err != nil {
  66. fmt.Println(err)
  67. fmt.Println("FAIL")
  68. ecode = 1
  69. }
  70. if ethereum != nil {
  71. ethereum.Stop()
  72. ethereum.WaitForShutdown()
  73. }
  74. }
  75. os.Exit(ecode)
  76. return
  77. }
  78. // otherwise, run the given test
  79. test, ok := bt[testname]
  80. if !ok {
  81. utils.Fatalf("Test file does not contain test named %q", testname)
  82. }
  83. ethereum, err := runOneBlockTest(ctx, test)
  84. if err != nil {
  85. utils.Fatalf("%v", err)
  86. }
  87. if rpc {
  88. fmt.Println("Block Test post state validated, starting RPC interface.")
  89. startEth(ctx, ethereum)
  90. utils.StartRPC(ethereum, ctx)
  91. ethereum.WaitForShutdown()
  92. }
  93. }
  94. func runOneBlockTest(ctx *cli.Context, test *tests.BlockTest) (*eth.Ethereum, error) {
  95. cfg := utils.MakeEthConfig(ClientIdentifier, Version, ctx)
  96. db, _ := ethdb.NewMemDatabase()
  97. cfg.NewDB = func(path string) (ethdb.Database, error) { return db, nil }
  98. cfg.MaxPeers = 0 // disable network
  99. cfg.Shh = false // disable whisper
  100. cfg.NAT = nil // disable port mapping
  101. ethereum, err := eth.New(cfg)
  102. if err != nil {
  103. return nil, err
  104. }
  105. // import the genesis block
  106. ethereum.ResetWithGenesisBlock(test.Genesis)
  107. // import pre accounts
  108. _, err = test.InsertPreState(db, cfg.AccountManager)
  109. if err != nil {
  110. return ethereum, fmt.Errorf("InsertPreState: %v", err)
  111. }
  112. cm := ethereum.BlockChain()
  113. validBlocks, err := test.TryBlocksInsert(cm)
  114. if err != nil {
  115. return ethereum, fmt.Errorf("Block Test load error: %v", err)
  116. }
  117. newDB, err := cm.State()
  118. if err != nil {
  119. return ethereum, fmt.Errorf("Block Test get state error: %v", err)
  120. }
  121. if err := test.ValidatePostState(newDB); err != nil {
  122. return ethereum, fmt.Errorf("post state validation failed: %v", err)
  123. }
  124. return ethereum, test.ValidateImportedHeaders(cm, validBlocks)
  125. }