gitlab.com/SiaPrime/SiaPrime@v1.4.1/node/api/miner_test.go (about)

     1  package api
     2  
     3  import (
     4  	"io/ioutil"
     5  	"testing"
     6  	"time"
     7  	"unsafe"
     8  
     9  	"gitlab.com/SiaPrime/SiaPrime/crypto"
    10  	"gitlab.com/SiaPrime/SiaPrime/types"
    11  )
    12  
    13  // TestMinerGET checks the GET call to the /miner endpoint.
    14  func TestMinerGET(t *testing.T) {
    15  	if testing.Short() {
    16  		t.SkipNow()
    17  	}
    18  	t.Parallel()
    19  	st, err := createServerTester(t.Name())
    20  	if err != nil {
    21  		t.Fatal(err)
    22  	}
    23  	defer st.server.panicClose()
    24  
    25  	// Get the api returned fields of the miner.
    26  	var mg MinerGET
    27  	err = st.getAPI("/miner", &mg)
    28  	if err != nil {
    29  		t.Fatal(err)
    30  	}
    31  
    32  	// Verify the correctness of the results.
    33  	blocksMined, staleBlocksMined := st.server.api.miner.BlocksMined()
    34  	if mg.BlocksMined != blocksMined {
    35  		t.Error("blocks mined did not succeed")
    36  	}
    37  	if mg.StaleBlocksMined != staleBlocksMined {
    38  		t.Error("stale blocks mined is incorrect")
    39  	}
    40  	if mg.CPUHashrate != st.server.api.miner.CPUHashrate() {
    41  		t.Error("mismatched cpu hashrate")
    42  	}
    43  	if mg.CPUMining != st.server.api.miner.CPUMining() {
    44  		t.Error("mismatched cpu miner status")
    45  	}
    46  }
    47  
    48  // TestMinerStartStop checks that the miner start and miner stop api endpoints
    49  // toggle the cpu miner.
    50  func TestMinerStartStop(t *testing.T) {
    51  	if testing.Short() {
    52  		t.SkipNow()
    53  	}
    54  	t.Parallel()
    55  	st, err := createServerTester(t.Name())
    56  	if err != nil {
    57  		t.Fatal(err)
    58  	}
    59  	defer st.server.panicClose()
    60  
    61  	// Start the cpu miner, give time for the first hashrate readings to
    62  	// appear.
    63  	err = st.stdGetAPI("/miner/start")
    64  	if err != nil {
    65  		t.Fatal(err)
    66  	}
    67  	time.Sleep(100 * time.Millisecond)
    68  	if !st.server.api.miner.CPUMining() {
    69  		t.Error("cpu miner is reporting that it is not on")
    70  	}
    71  
    72  	// Check the numbers through the status api call.
    73  	var mg MinerGET
    74  	err = st.getAPI("/miner", &mg)
    75  	if err != nil {
    76  		t.Fatal(err)
    77  	}
    78  	if !mg.CPUMining {
    79  		t.Error("cpu is not reporting through the api that it is mining")
    80  	}
    81  
    82  	// Stop the cpu miner and wait for the stop call to go through.
    83  	err = st.stdGetAPI("/miner/stop")
    84  	if err != nil {
    85  		t.Fatal(err)
    86  	}
    87  	time.Sleep(100 * time.Millisecond)
    88  	if st.server.api.miner.CPUMining() {
    89  		t.Error("cpu miner is reporting that it is on after being stopped")
    90  	}
    91  
    92  	// Check the numbers through the status api call.
    93  	err = st.getAPI("/miner", &mg)
    94  	if err != nil {
    95  		t.Fatal(err)
    96  	}
    97  	if mg.CPUMining {
    98  		t.Error("cpu is not reporting through the api that it is mining")
    99  	}
   100  }
   101  
   102  // TestMinerHeader checks that the header GET and POST calls are
   103  // useful tools for mining blocks.
   104  func TestMinerHeader(t *testing.T) {
   105  	if testing.Short() {
   106  		t.SkipNow()
   107  	}
   108  	t.Parallel()
   109  	st, err := createServerTester(t.Name())
   110  	if err != nil {
   111  		t.Fatal(err)
   112  	}
   113  	defer st.server.panicClose()
   114  	startingHeight := st.cs.Height()
   115  
   116  	// Get a header that can be used for mining.
   117  	resp, err := HttpGET("http://" + st.server.listener.Addr().String() + "/miner/header")
   118  	if err != nil {
   119  		t.Fatal(err)
   120  	}
   121  	defer resp.Body.Close()
   122  	targetAndHeader, err := ioutil.ReadAll(resp.Body)
   123  	if err != nil {
   124  		t.Fatal(err)
   125  	}
   126  
   127  	// Twiddle the header bits until a block has been found.
   128  	//
   129  	// Note: this test treats the target as hardcoded, if the testing target is
   130  	// changed, this test will also need to be changed.
   131  	if types.RootTarget[0] != 128 {
   132  		t.Fatal("test will fail because the testing constants have been unexpectedly changed")
   133  	}
   134  	var header [80]byte
   135  	copy(header[:], targetAndHeader[32:])
   136  	headerHash := crypto.HashObject(header)
   137  	for headerHash[0] >= types.RootTarget[0] {
   138  		*(*uint64)(unsafe.Pointer(&header[32])) += types.ASICHardforkFactor
   139  		headerHash = crypto.HashObject(header)
   140  	}
   141  
   142  	// Submit the solved header through the api and check that the height of
   143  	// the blockchain increases.
   144  	resp, err = HttpPOST("http://"+st.server.listener.Addr().String()+"/miner/header", string(header[:]))
   145  	if err != nil {
   146  		t.Fatal(err)
   147  	}
   148  	defer resp.Body.Close()
   149  	time.Sleep(500 * time.Millisecond)
   150  	if st.cs.Height() != startingHeight+1 {
   151  		t.Errorf("block height did not increase after trying to mine a block through the api, started at %v and ended at %v", startingHeight, st.cs.Height())
   152  	}
   153  }