github.com/jonasnick/go-ethereum@v0.7.12-0.20150216215225-22176f05d387/cmd/ethtest/main.go (about)

     1  /*
     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  */
    17  /**
    18   * @authors:
    19   * 	Jeffrey Wilcke <i@jev.io>
    20   */
    21  
    22  package main
    23  
    24  import (
    25  	"bytes"
    26  	"encoding/json"
    27  	"io"
    28  	"io/ioutil"
    29  	"log"
    30  	"os"
    31  	"strings"
    32  
    33  	"github.com/jonasnick/go-ethereum/ethdb"
    34  	"github.com/jonasnick/go-ethereum/ethutil"
    35  	"github.com/jonasnick/go-ethereum/logger"
    36  	"github.com/jonasnick/go-ethereum/state"
    37  	"github.com/jonasnick/go-ethereum/tests/helper"
    38  )
    39  
    40  type Account struct {
    41  	Balance string
    42  	Code    string
    43  	Nonce   string
    44  	Storage map[string]string
    45  }
    46  
    47  func StateObjectFromAccount(db ethutil.Database, addr string, account Account) *state.StateObject {
    48  	obj := state.NewStateObject(ethutil.Hex2Bytes(addr), db)
    49  	obj.SetBalance(ethutil.Big(account.Balance))
    50  
    51  	if ethutil.IsHex(account.Code) {
    52  		account.Code = account.Code[2:]
    53  	}
    54  	obj.Code = ethutil.Hex2Bytes(account.Code)
    55  	obj.Nonce = ethutil.Big(account.Nonce).Uint64()
    56  
    57  	return obj
    58  }
    59  
    60  type VmTest struct {
    61  	Callcreates interface{}
    62  	Env         map[string]string
    63  	Exec        map[string]string
    64  	Gas         string
    65  	Out         string
    66  	Post        map[string]Account
    67  	Pre         map[string]Account
    68  }
    69  
    70  func RunVmTest(r io.Reader) (failed int) {
    71  	tests := make(map[string]VmTest)
    72  
    73  	data, _ := ioutil.ReadAll(r)
    74  	err := json.Unmarshal(data, &tests)
    75  	if err != nil {
    76  		log.Fatalln(err)
    77  	}
    78  
    79  	for name, test := range tests {
    80  		db, _ := ethdb.NewMemDatabase()
    81  		state := state.New(nil, db)
    82  		for addr, account := range test.Pre {
    83  			obj := StateObjectFromAccount(db, addr, account)
    84  			state.SetStateObject(obj)
    85  		}
    86  
    87  		ret, _, gas, err := helper.RunVm(state, test.Env, test.Exec)
    88  		// When an error is returned it doesn't always mean the tests fails.
    89  		// Have to come up with some conditional failing mechanism.
    90  		if err != nil {
    91  			log.Println(err)
    92  		}
    93  
    94  		rexp := helper.FromHex(test.Out)
    95  		if bytes.Compare(rexp, ret) != 0 {
    96  			log.Printf("%s's return failed. Expected %x, got %x\n", name, rexp, ret)
    97  			failed = 1
    98  		}
    99  
   100  		if len(test.Gas) == 0 && err == nil {
   101  			log.Printf("0 gas indicates error but no error given by VM")
   102  			failed = 1
   103  		} else {
   104  			gexp := ethutil.Big(test.Gas)
   105  			if gexp.Cmp(gas) != 0 {
   106  				log.Printf("%s's gas failed. Expected %v, got %v\n", name, gexp, gas)
   107  				failed = 1
   108  			}
   109  		}
   110  
   111  		for addr, account := range test.Post {
   112  			obj := state.GetStateObject(helper.FromHex(addr))
   113  			for addr, value := range account.Storage {
   114  				v := obj.GetState(helper.FromHex(addr)).Bytes()
   115  				vexp := helper.FromHex(value)
   116  
   117  				if bytes.Compare(v, vexp) != 0 {
   118  					log.Printf("%s's : (%x: %s) storage failed. Expected %x, got %x (%v %v)\n", name, obj.Address()[0:4], addr, vexp, v, ethutil.BigD(vexp), ethutil.BigD(v))
   119  					failed = 1
   120  				}
   121  			}
   122  		}
   123  
   124  		logger.Flush()
   125  	}
   126  
   127  	return
   128  }
   129  
   130  func main() {
   131  	helper.Logger.SetLogLevel(5)
   132  
   133  	if len(os.Args) > 1 {
   134  		os.Exit(RunVmTest(strings.NewReader(os.Args[1])))
   135  	} else {
   136  		os.Exit(RunVmTest(os.Stdin))
   137  	}
   138  }