chainsvrwsntfns_test.go raw

   1  package btcjson_test
   2  
   3  import (
   4  	"bytes"
   5  	"encoding/json"
   6  	"fmt"
   7  	"reflect"
   8  	"testing"
   9  	
  10  	"github.com/p9c/p9/pkg/btcjson"
  11  )
  12  
  13  // TestChainSvrWsNtfns tests all of the chain server websocket-specific notifications marshal and unmarshal into valid
  14  // results include handling of optional fields being omitted in the marshalled command, while optional fields with
  15  // defaults have the default assigned on unmarshalled commands.
  16  func TestChainSvrWsNtfns(t *testing.T) {
  17  	t.Parallel()
  18  	tests := []struct {
  19  		name         string
  20  		newNtfn      func() (interface{}, error)
  21  		staticNtfn   func() interface{}
  22  		marshalled   string
  23  		unmarshalled interface{}
  24  	}{
  25  		{
  26  			name: "blockconnected",
  27  			newNtfn: func() (interface{}, error) {
  28  				return btcjson.NewCmd("blockconnected", "123", 100000, 123456789)
  29  			},
  30  			staticNtfn: func() interface{} {
  31  				return btcjson.NewBlockConnectedNtfn("123", 100000, 123456789)
  32  			},
  33  			marshalled: `{"jsonrpc":"1.0","method":"blockconnected","netparams":["123",100000,123456789],"id":null}`,
  34  			unmarshalled: &btcjson.BlockConnectedNtfn{
  35  				Hash:   "123",
  36  				Height: 100000,
  37  				Time:   123456789,
  38  			},
  39  		},
  40  		{
  41  			name: "blockdisconnected",
  42  			newNtfn: func() (interface{}, error) {
  43  				return btcjson.NewCmd("blockdisconnected", "123", 100000, 123456789)
  44  			},
  45  			staticNtfn: func() interface{} {
  46  				return btcjson.NewBlockDisconnectedNtfn("123", 100000, 123456789)
  47  			},
  48  			marshalled: `{"jsonrpc":"1.0","method":"blockdisconnected","netparams":["123",100000,123456789],"id":null}`,
  49  			unmarshalled: &btcjson.BlockDisconnectedNtfn{
  50  				Hash:   "123",
  51  				Height: 100000,
  52  				Time:   123456789,
  53  			},
  54  		},
  55  		{
  56  			name: "filteredblockconnected",
  57  			newNtfn: func() (interface{}, error) {
  58  				return btcjson.NewCmd("filteredblockconnected", 100000, "header", []string{"tx0", "tx1"})
  59  			},
  60  			staticNtfn: func() interface{} {
  61  				return btcjson.NewFilteredBlockConnectedNtfn(100000, "header", []string{"tx0", "tx1"})
  62  			},
  63  			marshalled: `{"jsonrpc":"1.0","method":"filteredblockconnected","netparams":[100000,"header",["tx0","tx1"]],"id":null}`,
  64  			unmarshalled: &btcjson.FilteredBlockConnectedNtfn{
  65  				Height:        100000,
  66  				Header:        "header",
  67  				SubscribedTxs: []string{"tx0", "tx1"},
  68  			},
  69  		},
  70  		{
  71  			name: "filteredblockdisconnected",
  72  			newNtfn: func() (interface{}, error) {
  73  				return btcjson.NewCmd("filteredblockdisconnected", 100000, "header")
  74  			},
  75  			staticNtfn: func() interface{} {
  76  				return btcjson.NewFilteredBlockDisconnectedNtfn(100000, "header")
  77  			},
  78  			marshalled: `{"jsonrpc":"1.0","method":"filteredblockdisconnected","netparams":[100000,"header"],"id":null}`,
  79  			unmarshalled: &btcjson.FilteredBlockDisconnectedNtfn{
  80  				Height: 100000,
  81  				Header: "header",
  82  			},
  83  		},
  84  		{
  85  			name: "recvtx",
  86  			newNtfn: func() (interface{}, error) {
  87  				return btcjson.NewCmd("recvtx", "001122", `{"height":100000,"hash":"123","index":0,"time":12345678}`)
  88  			},
  89  			staticNtfn: func() interface{} {
  90  				blockDetails := btcjson.BlockDetails{
  91  					Height: 100000,
  92  					Hash:   "123",
  93  					Index:  0,
  94  					Time:   12345678,
  95  				}
  96  				return btcjson.NewRecvTxNtfn("001122", &blockDetails)
  97  			},
  98  			marshalled: `{"jsonrpc":"1.0","method":"recvtx","netparams":["001122",{"height":100000,"hash":"123","index":0,"time":12345678}],"id":null}`,
  99  			unmarshalled: &btcjson.RecvTxNtfn{
 100  				HexTx: "001122",
 101  				Block: &btcjson.BlockDetails{
 102  					Height: 100000,
 103  					Hash:   "123",
 104  					Index:  0,
 105  					Time:   12345678,
 106  				},
 107  			},
 108  		},
 109  		{
 110  			name: "redeemingtx",
 111  			newNtfn: func() (interface{}, error) {
 112  				return btcjson.NewCmd("redeemingtx", "001122",
 113  					`{"height":100000,"hash":"123","index":0,"time":12345678}`,
 114  				)
 115  			},
 116  			staticNtfn: func() interface{} {
 117  				blockDetails := btcjson.BlockDetails{
 118  					Height: 100000,
 119  					Hash:   "123",
 120  					Index:  0,
 121  					Time:   12345678,
 122  				}
 123  				return btcjson.NewRedeemingTxNtfn("001122", &blockDetails)
 124  			},
 125  			marshalled: `{"jsonrpc":"1.0","method":"redeemingtx","netparams":["001122",{"height":100000,"hash":"123","index":0,"time":12345678}],"id":null}`,
 126  			unmarshalled: &btcjson.RedeemingTxNtfn{
 127  				HexTx: "001122",
 128  				Block: &btcjson.BlockDetails{
 129  					Height: 100000,
 130  					Hash:   "123",
 131  					Index:  0,
 132  					Time:   12345678,
 133  				},
 134  			},
 135  		},
 136  		{
 137  			name: "rescanfinished",
 138  			newNtfn: func() (interface{}, error) {
 139  				return btcjson.NewCmd("rescanfinished", "123", 100000, 12345678)
 140  			},
 141  			staticNtfn: func() interface{} {
 142  				return btcjson.NewRescanFinishedNtfn("123", 100000, 12345678)
 143  			},
 144  			marshalled: `{"jsonrpc":"1.0","method":"rescanfinished","netparams":["123",100000,12345678],"id":null}`,
 145  			unmarshalled: &btcjson.RescanFinishedNtfn{
 146  				Hash:   "123",
 147  				Height: 100000,
 148  				Time:   12345678,
 149  			},
 150  		},
 151  		{
 152  			name: "rescanprogress",
 153  			newNtfn: func() (interface{}, error) {
 154  				return btcjson.NewCmd("rescanprogress", "123", 100000, 12345678)
 155  			},
 156  			staticNtfn: func() interface{} {
 157  				return btcjson.NewRescanProgressNtfn("123", 100000, 12345678)
 158  			},
 159  			marshalled: `{"jsonrpc":"1.0","method":"rescanprogress","netparams":["123",100000,12345678],"id":null}`,
 160  			unmarshalled: &btcjson.RescanProgressNtfn{
 161  				Hash:   "123",
 162  				Height: 100000,
 163  				Time:   12345678,
 164  			},
 165  		},
 166  		{
 167  			name: "txaccepted",
 168  			newNtfn: func() (interface{}, error) {
 169  				return btcjson.NewCmd("txaccepted", "123", 1.5)
 170  			},
 171  			staticNtfn: func() interface{} {
 172  				return btcjson.NewTxAcceptedNtfn("123", 1.5)
 173  			},
 174  			marshalled: `{"jsonrpc":"1.0","method":"txaccepted","netparams":["123",1.5],"id":null}`,
 175  			unmarshalled: &btcjson.TxAcceptedNtfn{
 176  				TxID:   "123",
 177  				Amount: 1.5,
 178  			},
 179  		},
 180  		{
 181  			name: "txacceptedverbose",
 182  			newNtfn: func() (interface{}, error) {
 183  				return btcjson.NewCmd("txacceptedverbose",
 184  					`{"hex":"001122","txid":"123","version":1,"locktime":4294967295,"vin":null,"vout":null,"confirmations":0}`,
 185  				)
 186  			},
 187  			staticNtfn: func() interface{} {
 188  				txResult := btcjson.TxRawResult{
 189  					Hex:           "001122",
 190  					Txid:          "123",
 191  					Version:       1,
 192  					LockTime:      4294967295,
 193  					Vin:           nil,
 194  					Vout:          nil,
 195  					Confirmations: 0,
 196  				}
 197  				return btcjson.NewTxAcceptedVerboseNtfn(txResult)
 198  			},
 199  			marshalled: `{"jsonrpc":"1.0","method":"txacceptedverbose","netparams":[{"hex":"001122","txid":"123","version":1,"locktime":4294967295,"vin":null,"vout":null}],"id":null}`,
 200  			unmarshalled: &btcjson.TxAcceptedVerboseNtfn{
 201  				RawTx: btcjson.TxRawResult{
 202  					Hex:           "001122",
 203  					Txid:          "123",
 204  					Version:       1,
 205  					LockTime:      4294967295,
 206  					Vin:           nil,
 207  					Vout:          nil,
 208  					Confirmations: 0,
 209  				},
 210  			},
 211  		},
 212  		{
 213  			name: "relevanttxaccepted",
 214  			newNtfn: func() (interface{}, error) {
 215  				return btcjson.NewCmd("relevanttxaccepted", "001122")
 216  			},
 217  			staticNtfn: func() interface{} {
 218  				return btcjson.NewRelevantTxAcceptedNtfn("001122")
 219  			},
 220  			marshalled: `{"jsonrpc":"1.0","method":"relevanttxaccepted","netparams":["001122"],"id":null}`,
 221  			unmarshalled: &btcjson.RelevantTxAcceptedNtfn{
 222  				Transaction: "001122",
 223  			},
 224  		},
 225  	}
 226  	t.Logf("Running %d tests", len(tests))
 227  	for i, test := range tests {
 228  		// Marshal the notification as created by the new static creation function.  The ID is nil for notifications.
 229  		marshalled, e := btcjson.MarshalCmd(nil, test.staticNtfn())
 230  		if e != nil {
 231  			t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i,
 232  				test.name, e,
 233  			)
 234  			continue
 235  		}
 236  		if !bytes.Equal(marshalled, []byte(test.marshalled)) {
 237  			t.Errorf("Test #%d (%s) unexpected marshalled data - "+
 238  				"got %s, want %s", i, test.name, marshalled,
 239  				test.marshalled,
 240  			)
 241  			continue
 242  		}
 243  		// Ensure the notification is created without error via the generic new notification creation function.
 244  		cmd, e := test.newNtfn()
 245  		if e != nil {
 246  			t.Errorf("Test #%d (%s) unexpected NewCmd error: %v ",
 247  				i, test.name, e,
 248  			)
 249  		}
 250  		// Marshal the notification as created by the generic new notification creation function. The ID is nil for
 251  		// notifications.
 252  		marshalled, e = btcjson.MarshalCmd(nil, cmd)
 253  		if e != nil {
 254  			t.Errorf("MarshalCmd #%d (%s) unexpected error: %v", i,
 255  				test.name, e,
 256  			)
 257  			continue
 258  		}
 259  		if !bytes.Equal(marshalled, []byte(test.marshalled)) {
 260  			t.Errorf("Test #%d (%s) unexpected marshalled data - "+
 261  				"got %s, want %s", i, test.name, marshalled,
 262  				test.marshalled,
 263  			)
 264  			continue
 265  		}
 266  		var request btcjson.Request
 267  		if e = json.Unmarshal(marshalled, &request); E.Chk(e) {
 268  			t.Errorf("Test #%d (%s) unexpected error while "+
 269  				"unmarshalling JSON-RPC request: %v", i,
 270  				test.name, e,
 271  			)
 272  			continue
 273  		}
 274  		cmd, e = btcjson.UnmarshalCmd(&request)
 275  		if e != nil {
 276  			t.Errorf("UnmarshalCmd #%d (%s) unexpected error: %v", i,
 277  				test.name, e,
 278  			)
 279  			continue
 280  		}
 281  		if !reflect.DeepEqual(cmd, test.unmarshalled) {
 282  			t.Errorf("Test #%d (%s) unexpected unmarshalled command "+
 283  				"- got %s, want %s", i, test.name,
 284  				fmt.Sprintf("(%T) %+[1]v", cmd),
 285  				fmt.Sprintf("(%T) %+[1]v\n", test.unmarshalled),
 286  			)
 287  			continue
 288  		}
 289  	}
 290  }
 291