@ -22,6 +22,7 @@ import (
"math/big"
"net/http"
"net/http/httptest"
"strconv"
"testing"
"time"
@ -74,6 +75,50 @@ func TestRemoteNotify(t *testing.T) {
}
}
// Tests whether remote HTTP servers are correctly notified of new work. (Full pending block body / --miner.notify.full)
func TestRemoteNotifyFull ( t * testing . T ) {
// Start a simple web server to capture notifications.
sink := make ( chan map [ string ] interface { } )
server := httptest . NewServer ( http . HandlerFunc ( func ( w http . ResponseWriter , req * http . Request ) {
blob , err := ioutil . ReadAll ( req . Body )
if err != nil {
t . Errorf ( "failed to read miner notification: %v" , err )
}
var work map [ string ] interface { }
if err := json . Unmarshal ( blob , & work ) ; err != nil {
t . Errorf ( "failed to unmarshal miner notification: %v" , err )
}
sink <- work
} ) )
defer server . Close ( )
// Create the custom ethash engine.
config := Config {
PowMode : ModeTest ,
NotifyFull : true ,
Log : testlog . Logger ( t , log . LvlWarn ) ,
}
ethash := New ( config , [ ] string { server . URL } , false )
defer ethash . Close ( )
// Stream a work task and ensure the notification bubbles out.
header := & types . Header { Number : big . NewInt ( 1 ) , Difficulty : big . NewInt ( 100 ) }
block := types . NewBlockWithHeader ( header )
ethash . Seal ( nil , block , nil , nil )
select {
case work := <- sink :
if want := "0x" + strconv . FormatUint ( header . Number . Uint64 ( ) , 16 ) ; work [ "number" ] != want {
t . Errorf ( "pending block number mismatch: have %v, want %v" , work [ "number" ] , want )
}
if want := "0x" + header . Difficulty . Text ( 16 ) ; work [ "difficulty" ] != want {
t . Errorf ( "pending block difficulty mismatch: have %s, want %s" , work [ "difficulty" ] , want )
}
case <- time . After ( 3 * time . Second ) :
t . Fatalf ( "notification timed out" )
}
}
// Tests that pushing work packages fast to the miner doesn't cause any data race
// issues in the notifications.
func TestRemoteMultiNotify ( t * testing . T ) {
@ -119,6 +164,55 @@ func TestRemoteMultiNotify(t *testing.T) {
}
}
// Tests that pushing work packages fast to the miner doesn't cause any data race
// issues in the notifications. Full pending block body / --miner.notify.full)
func TestRemoteMultiNotifyFull ( t * testing . T ) {
// Start a simple web server to capture notifications.
sink := make ( chan map [ string ] interface { } , 64 )
server := httptest . NewServer ( http . HandlerFunc ( func ( w http . ResponseWriter , req * http . Request ) {
blob , err := ioutil . ReadAll ( req . Body )
if err != nil {
t . Errorf ( "failed to read miner notification: %v" , err )
}
var work map [ string ] interface { }
if err := json . Unmarshal ( blob , & work ) ; err != nil {
t . Errorf ( "failed to unmarshal miner notification: %v" , err )
}
sink <- work
} ) )
defer server . Close ( )
// Create the custom ethash engine.
config := Config {
PowMode : ModeTest ,
NotifyFull : true ,
Log : testlog . Logger ( t , log . LvlWarn ) ,
}
ethash := New ( config , [ ] string { server . URL } , false )
defer ethash . Close ( )
// Provide a results reader.
// Otherwise the unread results will be logged asynchronously
// and this can happen after the test is finished, causing a panic.
results := make ( chan * types . Block , cap ( sink ) )
// Stream a lot of work task and ensure all the notifications bubble out.
for i := 0 ; i < cap ( sink ) ; i ++ {
header := & types . Header { Number : big . NewInt ( int64 ( i ) ) , Difficulty : big . NewInt ( 100 ) }
block := types . NewBlockWithHeader ( header )
ethash . Seal ( nil , block , results , nil )
}
for i := 0 ; i < cap ( sink ) ; i ++ {
select {
case <- sink :
<- results
case <- time . After ( 10 * time . Second ) :
t . Fatalf ( "notification %d timed out" , i )
}
}
}
// Tests whether stale solutions are correctly processed.
func TestStaleSubmission ( t * testing . T ) {
ethash := NewTester ( nil , true )