miner_test.go 3.86 KB
Newer Older
1 2 3
package api

import (
David Vorick's avatar
David Vorick committed
4
	"io/ioutil"
5
	"testing"
6
	"time"
David Vorick's avatar
David Vorick committed
7 8 9

	"github.com/NebulousLabs/Sia/crypto"
	"github.com/NebulousLabs/Sia/types"
10 11
)

12 13
// TestMinerGET checks the GET call to the /miner endpoint.
func TestMinerGET(t *testing.T) {
14 15 16
	if testing.Short() {
		t.SkipNow()
	}
17
	t.Parallel()
18
	st, err := createServerTester(t.Name())
19 20 21
	if err != nil {
		t.Fatal(err)
	}
22
	defer st.server.panicClose()
23 24 25 26 27 28 29 30 31

	// Get the api returned fields of the miner.
	var mg MinerGET
	err = st.getAPI("/miner", &mg)
	if err != nil {
		t.Fatal(err)
	}

	// Verify the correctness of the results.
32
	blocksMined, staleBlocksMined := st.server.api.miner.BlocksMined()
33 34 35 36 37 38
	if mg.BlocksMined != blocksMined {
		t.Error("blocks mined did not succeed")
	}
	if mg.StaleBlocksMined != staleBlocksMined {
		t.Error("stale blocks mined is incorrect")
	}
39
	if mg.CPUHashrate != st.server.api.miner.CPUHashrate() {
40 41
		t.Error("mismatched cpu hashrate")
	}
42
	if mg.CPUMining != st.server.api.miner.CPUMining() {
43 44 45
		t.Error("mismatched cpu miner status")
	}
}
46

47
// TestMinerStartStop checks that the miner start and miner stop api endpoints
48
// toggle the cpu miner.
49
func TestMinerStartStop(t *testing.T) {
50 51 52
	if testing.Short() {
		t.SkipNow()
	}
53
	t.Parallel()
54
	st, err := createServerTester(t.Name())
55 56 57
	if err != nil {
		t.Fatal(err)
	}
58
	defer st.server.panicClose()
59 60 61

	// Start the cpu miner, give time for the first hashrate readings to
	// appear.
62
	err = st.stdGetAPI("/miner/start")
63 64 65
	if err != nil {
		t.Fatal(err)
	}
David Vorick's avatar
David Vorick committed
66
	time.Sleep(100 * time.Millisecond)
67
	if !st.server.api.miner.CPUMining() {
68 69 70 71 72 73 74 75 76 77
		t.Error("cpu miner is reporting that it is not on")
	}

	// Check the numbers through the status api call.
	var mg MinerGET
	err = st.getAPI("/miner", &mg)
	if err != nil {
		t.Fatal(err)
	}
	if !mg.CPUMining {
78
		t.Error("cpu is not reporting through the api that it is mining")
79 80 81
	}

	// Stop the cpu miner and wait for the stop call to go through.
82
	err = st.stdGetAPI("/miner/stop")
83 84 85
	if err != nil {
		t.Fatal(err)
	}
David Vorick's avatar
David Vorick committed
86
	time.Sleep(100 * time.Millisecond)
87
	if st.server.api.miner.CPUMining() {
88
		t.Error("cpu miner is reporting that it is on after being stopped")
89 90 91 92 93 94 95 96
	}

	// Check the numbers through the status api call.
	err = st.getAPI("/miner", &mg)
	if err != nil {
		t.Fatal(err)
	}
	if mg.CPUMining {
97
		t.Error("cpu is not reporting through the api that it is mining")
98 99
	}
}
David Vorick's avatar
David Vorick committed
100

101
// TestMinerHeader checks that the header GET and POST calls are
David Vorick's avatar
David Vorick committed
102
// useful tools for mining blocks.
103
func TestMinerHeader(t *testing.T) {
David Vorick's avatar
David Vorick committed
104 105 106
	if testing.Short() {
		t.SkipNow()
	}
107
	t.Parallel()
108
	st, err := createServerTester(t.Name())
David Vorick's avatar
David Vorick committed
109 110 111
	if err != nil {
		t.Fatal(err)
	}
112
	defer st.server.panicClose()
David Vorick's avatar
David Vorick committed
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
	startingHeight := st.cs.Height()

	// Get a header that can be used for mining.
	resp, err := HttpGET("http://" + st.server.listener.Addr().String() + "/miner/header")
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()
	targetAndHeader, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		t.Fatal(err)
	}

	// Twiddle the header bits until a block has been found.
	//
	// Note: this test treats the target as hardcoded, if the testing target is
	// changed, this test will also need to be changed.
	if types.RootTarget[0] != 128 {
		t.Fatal("test will fail because the testing constants have been unexpectedly changed")
	}
	var header [80]byte
	copy(header[:], targetAndHeader[32:])
	headerHash := crypto.HashObject(header)
	for headerHash[0] >= types.RootTarget[0] {
		header[35]++
		headerHash = crypto.HashObject(header)
	}

	// Submit the solved header through the api and check that the height of
	// the blockchain increases.
	resp, err = HttpPOST("http://"+st.server.listener.Addr().String()+"/miner/header", string(header[:]))
	if err != nil {
		t.Fatal(err)
	}
	defer resp.Body.Close()
	time.Sleep(500 * time.Millisecond)
	if st.cs.Height() != startingHeight+1 {
150
		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())
David Vorick's avatar
David Vorick committed
151 152
	}
}