itest: refactor testRestAPI
This commit is contained in:
3 files changed
+116
-121
No files matched your search
@@ -287,4 +287,8 @@ var allTestCasesTemp = []*lntemp.TestCase{
|
|||||||
Name: "resolution handoff",
|
Name: "resolution handoff",
|
||||||
TestFunc: testResHandoff,
|
TestFunc: testResHandoff,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "REST API",
|
||||||
|
TestFunc: testRestAPI,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
+112
-117
@@ -2,7 +2,6 @@ package itest
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
@@ -24,8 +23,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/verrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/verrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
"github.com/lightningnetwork/lnd/lntemp"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -57,19 +56,21 @@ var (
|
|||||||
|
|
||||||
// testRestAPI tests that the most important features of the REST API work
|
// testRestAPI tests that the most important features of the REST API work
|
||||||
// correctly.
|
// correctly.
|
||||||
func testRestAPI(net *lntest.NetworkHarness, ht *harnessTest) {
|
func testRestAPI(ht *lntemp.HarnessTest) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
run func(*testing.T, *lntest.HarnessNode, *lntest.HarnessNode)
|
run func(*testing.T, *node.HarnessNode, *node.HarnessNode)
|
||||||
}{{
|
}{{
|
||||||
name: "simple GET",
|
name: "simple GET",
|
||||||
run: func(t *testing.T, a, b *lntest.HarnessNode) {
|
run: func(t *testing.T, a, b *node.HarnessNode) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
// Check that the parsing into the response proto
|
// Check that the parsing into the response proto
|
||||||
// message works.
|
// message works.
|
||||||
resp := &lnrpc.GetInfoResponse{}
|
resp := &lnrpc.GetInfoResponse{}
|
||||||
err := invokeGET(a, "/v1/getinfo", resp)
|
err := invokeGET(a, "/v1/getinfo", resp)
|
||||||
require.Nil(t, err, "getinfo")
|
require.Nil(t, err, "getinfo")
|
||||||
assert.Equal(t, "#3399ff", resp.Color, "node color")
|
require.Equal(t, "#3399ff", resp.Color, "node color")
|
||||||
|
|
||||||
// Make sure we get the correct field names (snake
|
// Make sure we get the correct field names (snake
|
||||||
// case).
|
// case).
|
||||||
@@ -77,20 +78,22 @@ func testRestAPI(net *lntest.NetworkHarness, ht *harnessTest) {
|
|||||||
a, "/v1/getinfo", "GET", nil, nil,
|
a, "/v1/getinfo", "GET", nil, nil,
|
||||||
)
|
)
|
||||||
require.Nil(t, err, "getinfo")
|
require.Nil(t, err, "getinfo")
|
||||||
assert.Contains(
|
require.Contains(
|
||||||
t, string(resp2), "best_header_timestamp",
|
t, string(resp2), "best_header_timestamp",
|
||||||
"getinfo",
|
"getinfo",
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "simple POST and GET with query param",
|
name: "simple POST and GET with query param",
|
||||||
run: func(t *testing.T, a, b *lntest.HarnessNode) {
|
run: func(t *testing.T, a, b *node.HarnessNode) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
// Add an invoice, testing POST in the process.
|
// Add an invoice, testing POST in the process.
|
||||||
req := &lnrpc.Invoice{Value: 1234}
|
req := &lnrpc.Invoice{Value: 1234}
|
||||||
resp := &lnrpc.AddInvoiceResponse{}
|
resp := &lnrpc.AddInvoiceResponse{}
|
||||||
err := invokePOST(a, "/v1/invoices", req, resp)
|
err := invokePOST(a, "/v1/invoices", req, resp)
|
||||||
require.Nil(t, err, "add invoice")
|
require.Nil(t, err, "add invoice")
|
||||||
assert.Equal(t, 32, len(resp.RHash), "invoice rhash")
|
require.Equal(t, 32, len(resp.RHash), "invoice rhash")
|
||||||
|
|
||||||
// Make sure we can call a GET endpoint with a hex
|
// Make sure we can call a GET endpoint with a hex
|
||||||
// encoded URL part.
|
// encoded URL part.
|
||||||
@@ -98,11 +101,14 @@ func testRestAPI(net *lntest.NetworkHarness, ht *harnessTest) {
|
|||||||
resp2 := &lnrpc.Invoice{}
|
resp2 := &lnrpc.Invoice{}
|
||||||
err = invokeGET(a, url, resp2)
|
err = invokeGET(a, url, resp2)
|
||||||
require.Nil(t, err, "query invoice")
|
require.Nil(t, err, "query invoice")
|
||||||
assert.Equal(t, int64(1234), resp2.Value, "invoice amt")
|
require.Equal(t, int64(1234), resp2.Value,
|
||||||
|
"invoice amt")
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "GET with base64 encoded byte slice in path",
|
name: "GET with base64 encoded byte slice in path",
|
||||||
run: func(t *testing.T, a, b *lntest.HarnessNode) {
|
run: func(t *testing.T, a, b *node.HarnessNode) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
url := "/v2/router/mc/probability/%s/%s/%d"
|
url := "/v2/router/mc/probability/%s/%s/%d"
|
||||||
url = fmt.Sprintf(
|
url = fmt.Sprintf(
|
||||||
url, urlEnc.EncodeToString(a.PubKey[:]),
|
url, urlEnc.EncodeToString(a.PubKey[:]),
|
||||||
@@ -115,38 +121,37 @@ func testRestAPI(net *lntest.NetworkHarness, ht *harnessTest) {
|
|||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "GET with map type query param",
|
name: "GET with map type query param",
|
||||||
run: func(t *testing.T, a, b *lntest.HarnessNode) {
|
run: func(t *testing.T, a, b *node.HarnessNode) {
|
||||||
// Get a new wallet address from Alice.
|
t.Helper()
|
||||||
ctxb := context.Background()
|
|
||||||
newAddrReq := &lnrpc.NewAddressRequest{
|
// Use a fake address.
|
||||||
Type: lnrpc.AddressType_WITNESS_PUBKEY_HASH,
|
addr := "bcrt1qlutnwklt4u2548cufrjmsjclewugr9lcpnkzag"
|
||||||
}
|
|
||||||
addrRes, err := a.NewAddress(ctxb, newAddrReq)
|
|
||||||
require.Nil(t, err, "get address")
|
|
||||||
|
|
||||||
// Create the full URL with the map query param.
|
// Create the full URL with the map query param.
|
||||||
url := "/v1/transactions/fee?target_conf=%d&" +
|
url := "/v1/transactions/fee?target_conf=%d&" +
|
||||||
"AddrToAmount[%s]=%d"
|
"AddrToAmount[%s]=%d"
|
||||||
url = fmt.Sprintf(url, 2, addrRes.Address, 50000)
|
url = fmt.Sprintf(url, 2, addr, 50000)
|
||||||
resp := &lnrpc.EstimateFeeResponse{}
|
resp := &lnrpc.EstimateFeeResponse{}
|
||||||
err = invokeGET(a, url, resp)
|
err := invokeGET(a, url, resp)
|
||||||
require.Nil(t, err, "estimate fee")
|
require.Nil(t, err, "estimate fee")
|
||||||
assert.Greater(t, resp.FeeSat, int64(253), "fee")
|
require.Greater(t, resp.FeeSat, int64(253), "fee")
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "sub RPC servers REST support",
|
name: "sub RPC servers REST support",
|
||||||
run: func(t *testing.T, a, b *lntest.HarnessNode) {
|
run: func(t *testing.T, a, b *node.HarnessNode) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
// Query autopilot status.
|
// Query autopilot status.
|
||||||
res1 := &autopilotrpc.StatusResponse{}
|
res1 := &autopilotrpc.StatusResponse{}
|
||||||
err := invokeGET(a, "/v2/autopilot/status", res1)
|
err := invokeGET(a, "/v2/autopilot/status", res1)
|
||||||
require.Nil(t, err, "autopilot status")
|
require.Nil(t, err, "autopilot status")
|
||||||
assert.Equal(t, false, res1.Active, "autopilot status")
|
require.Equal(t, false, res1.Active, "autopilot status")
|
||||||
|
|
||||||
// Query the version RPC.
|
// Query the version RPC.
|
||||||
res2 := &verrpc.Version{}
|
res2 := &verrpc.Version{}
|
||||||
err = invokeGET(a, "/v2/versioner/version", res2)
|
err = invokeGET(a, "/v2/versioner/version", res2)
|
||||||
require.Nil(t, err, "version")
|
require.Nil(t, err, "version")
|
||||||
assert.Greater(
|
require.Greater(
|
||||||
t, res2.AppMinor, uint32(0), "lnd minor version",
|
t, res2.AppMinor, uint32(0), "lnd minor version",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -157,11 +162,13 @@ func testRestAPI(net *lntest.NetworkHarness, ht *harnessTest) {
|
|||||||
a, "/v2/wallet/address/next", req1, res3,
|
a, "/v2/wallet/address/next", req1, res3,
|
||||||
)
|
)
|
||||||
require.Nil(t, err, "address")
|
require.Nil(t, err, "address")
|
||||||
assert.NotEmpty(t, res3.Addr, "address")
|
require.NotEmpty(t, res3.Addr, "address")
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "CORS headers",
|
name: "CORS headers",
|
||||||
run: func(t *testing.T, a, b *lntest.HarnessNode) {
|
run: func(t *testing.T, a, b *node.HarnessNode) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
// Alice allows all origins. Make sure we get the same
|
// Alice allows all origins. Make sure we get the same
|
||||||
// value back in the CORS header that we send in the
|
// value back in the CORS header that we send in the
|
||||||
// Origin header.
|
// Origin header.
|
||||||
@@ -171,12 +178,12 @@ func testRestAPI(net *lntest.NetworkHarness, ht *harnessTest) {
|
|||||||
a, "/v1/getinfo", "OPTIONS", nil, reqHeaders,
|
a, "/v1/getinfo", "OPTIONS", nil, reqHeaders,
|
||||||
)
|
)
|
||||||
require.Nil(t, err, "getinfo")
|
require.Nil(t, err, "getinfo")
|
||||||
assert.Equal(
|
require.Equal(
|
||||||
t, "https://foo.bar:9999",
|
t, "https://foo.bar:9999",
|
||||||
resHeaders.Get("Access-Control-Allow-Origin"),
|
resHeaders.Get("Access-Control-Allow-Origin"),
|
||||||
"CORS header",
|
"CORS header",
|
||||||
)
|
)
|
||||||
assert.Equal(t, 0, len(body))
|
require.Equal(t, 0, len(body))
|
||||||
|
|
||||||
// Make sure that we don't get a value set for Bob which
|
// Make sure that we don't get a value set for Bob which
|
||||||
// doesn't allow any CORS origin.
|
// doesn't allow any CORS origin.
|
||||||
@@ -184,17 +191,17 @@ func testRestAPI(net *lntest.NetworkHarness, ht *harnessTest) {
|
|||||||
b, "/v1/getinfo", "OPTIONS", nil, reqHeaders,
|
b, "/v1/getinfo", "OPTIONS", nil, reqHeaders,
|
||||||
)
|
)
|
||||||
require.Nil(t, err, "getinfo")
|
require.Nil(t, err, "getinfo")
|
||||||
assert.Equal(
|
require.Equal(
|
||||||
t, "",
|
t, "",
|
||||||
resHeaders.Get("Access-Control-Allow-Origin"),
|
resHeaders.Get("Access-Control-Allow-Origin"),
|
||||||
"CORS header",
|
"CORS header",
|
||||||
)
|
)
|
||||||
assert.Equal(t, 0, len(body))
|
require.Equal(t, 0, len(body))
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
wsTestCases := []struct {
|
wsTestCases := []struct {
|
||||||
name string
|
name string
|
||||||
run func(ht *harnessTest, net *lntest.NetworkHarness)
|
run func(ht *lntemp.HarnessTest)
|
||||||
}{{
|
}{{
|
||||||
name: "websocket subscription",
|
name: "websocket subscription",
|
||||||
run: wsTestCaseSubscription,
|
run: wsTestCaseSubscription,
|
||||||
@@ -212,39 +219,33 @@ func testRestAPI(net *lntest.NetworkHarness, ht *harnessTest) {
|
|||||||
// Make sure Alice allows all CORS origins. Bob will keep the default.
|
// Make sure Alice allows all CORS origins. Bob will keep the default.
|
||||||
// We also make sure the ping/pong messages are sent very often, so we
|
// We also make sure the ping/pong messages are sent very often, so we
|
||||||
// can test them without waiting half a minute.
|
// can test them without waiting half a minute.
|
||||||
net.Alice.Cfg.ExtraArgs = append(
|
alice, bob := ht.Alice, ht.Bob
|
||||||
net.Alice.Cfg.ExtraArgs, "--restcors=\"*\"",
|
alice.Cfg.ExtraArgs = append(
|
||||||
|
alice.Cfg.ExtraArgs, "--restcors=\"*\"",
|
||||||
fmt.Sprintf("--ws-ping-interval=%s", pingInterval),
|
fmt.Sprintf("--ws-ping-interval=%s", pingInterval),
|
||||||
fmt.Sprintf("--ws-pong-wait=%s", pongWait),
|
fmt.Sprintf("--ws-pong-wait=%s", pongWait),
|
||||||
)
|
)
|
||||||
err := net.RestartNode(net.Alice, nil)
|
ht.RestartNode(alice)
|
||||||
if err != nil {
|
|
||||||
ht.t.Fatalf("Could not restart Alice to set CORS config: %v",
|
|
||||||
err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
tc := tc
|
||||||
ht.t.Run(tc.name, func(t *testing.T) {
|
ht.Run(tc.name, func(t *testing.T) {
|
||||||
tc.run(t, net.Alice, net.Bob)
|
tc.run(t, alice, bob)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range wsTestCases {
|
for _, tc := range wsTestCases {
|
||||||
tc := tc
|
tc := tc
|
||||||
ht.t.Run(tc.name, func(t *testing.T) {
|
ht.Run(tc.name, func(t *testing.T) {
|
||||||
ht := &harnessTest{
|
st := ht.Subtest(t)
|
||||||
t: t, testCase: ht.testCase, lndHarness: net,
|
tc.run(st)
|
||||||
}
|
|
||||||
tc.run(ht, net)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func wsTestCaseSubscription(ht *harnessTest, net *lntest.NetworkHarness) {
|
func wsTestCaseSubscription(ht *lntemp.HarnessTest) {
|
||||||
// Find out the current best block so we can subscribe to the next one.
|
// Find out the current best block so we can subscribe to the next one.
|
||||||
hash, height, err := net.Miner.Client.GetBestBlock()
|
hash, height := ht.Miner.GetBestBlock()
|
||||||
require.Nil(ht.t, err, "get best block")
|
|
||||||
|
|
||||||
// Create a new subscription to get block epoch events.
|
// Create a new subscription to get block epoch events.
|
||||||
req := &chainrpc.BlockEpoch{
|
req := &chainrpc.BlockEpoch{
|
||||||
@@ -252,11 +253,11 @@ func wsTestCaseSubscription(ht *harnessTest, net *lntest.NetworkHarness) {
|
|||||||
Height: uint32(height),
|
Height: uint32(height),
|
||||||
}
|
}
|
||||||
url := "/v2/chainnotifier/register/blocks"
|
url := "/v2/chainnotifier/register/blocks"
|
||||||
c, err := openWebSocket(net.Alice, url, "POST", req, nil)
|
c, err := openWebSocket(ht.Alice, url, "POST", req, nil)
|
||||||
require.Nil(ht.t, err, "websocket")
|
require.NoError(ht, err, "websocket")
|
||||||
defer func() {
|
defer func() {
|
||||||
err := c.WriteMessage(websocket.CloseMessage, closeMsg)
|
err := c.WriteMessage(websocket.CloseMessage, closeMsg)
|
||||||
require.NoError(ht.t, err)
|
require.NoError(ht, err)
|
||||||
_ = c.Close()
|
_ = c.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -300,30 +301,25 @@ func wsTestCaseSubscription(ht *harnessTest, net *lntest.NetworkHarness) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// Mine a block and make sure we get a message for it.
|
// Mine a block and make sure we get a message for it.
|
||||||
blockHashes, err := net.Miner.Client.Generate(1)
|
blockHashes := ht.Miner.GenerateBlocks(1)
|
||||||
require.Nil(ht.t, err, "generate blocks")
|
|
||||||
assert.Equal(ht.t, 1, len(blockHashes), "num blocks")
|
|
||||||
select {
|
select {
|
||||||
case msg := <-msgChan:
|
case msg := <-msgChan:
|
||||||
assert.Equal(
|
require.Equal(
|
||||||
ht.t, blockHashes[0].CloneBytes(), msg.Hash,
|
ht, blockHashes[0].CloneBytes(), msg.Hash,
|
||||||
"block hash",
|
"block hash",
|
||||||
)
|
)
|
||||||
|
|
||||||
case err := <-errChan:
|
case err := <-errChan:
|
||||||
ht.t.Fatalf("Received error from WS: %v", err)
|
ht.Fatalf("Received error from WS: %v", err)
|
||||||
|
|
||||||
case <-timeout:
|
case <-timeout:
|
||||||
ht.t.Fatalf("Timeout before message was received")
|
ht.Fatalf("Timeout before message was received")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func wsTestCaseSubscriptionMacaroon(ht *harnessTest,
|
func wsTestCaseSubscriptionMacaroon(ht *lntemp.HarnessTest) {
|
||||||
net *lntest.NetworkHarness) {
|
|
||||||
|
|
||||||
// Find out the current best block so we can subscribe to the next one.
|
// Find out the current best block so we can subscribe to the next one.
|
||||||
hash, height, err := net.Miner.Client.GetBestBlock()
|
hash, height := ht.Miner.GetBestBlock()
|
||||||
require.Nil(ht.t, err, "get best block")
|
|
||||||
|
|
||||||
// Create a new subscription to get block epoch events.
|
// Create a new subscription to get block epoch events.
|
||||||
req := &chainrpc.BlockEpoch{
|
req := &chainrpc.BlockEpoch{
|
||||||
@@ -335,22 +331,23 @@ func wsTestCaseSubscriptionMacaroon(ht *harnessTest,
|
|||||||
// This time we send the macaroon in the special header
|
// This time we send the macaroon in the special header
|
||||||
// Sec-Websocket-Protocol which is the only header field available to
|
// Sec-Websocket-Protocol which is the only header field available to
|
||||||
// browsers when opening a WebSocket.
|
// browsers when opening a WebSocket.
|
||||||
mac, err := net.Alice.ReadMacaroon(
|
alice := ht.Alice
|
||||||
net.Alice.AdminMacPath(), defaultTimeout,
|
mac, err := alice.ReadMacaroon(
|
||||||
|
alice.Cfg.AdminMacPath, defaultTimeout,
|
||||||
)
|
)
|
||||||
require.NoError(ht.t, err, "read admin mac")
|
require.NoError(ht, err, "read admin mac")
|
||||||
macBytes, err := mac.MarshalBinary()
|
macBytes, err := mac.MarshalBinary()
|
||||||
require.NoError(ht.t, err, "marshal admin mac")
|
require.NoError(ht, err, "marshal admin mac")
|
||||||
|
|
||||||
customHeader := make(http.Header)
|
customHeader := make(http.Header)
|
||||||
customHeader.Set(lnrpc.HeaderWebSocketProtocol, fmt.Sprintf(
|
customHeader.Set(lnrpc.HeaderWebSocketProtocol, fmt.Sprintf(
|
||||||
"Grpc-Metadata-Macaroon+%s", hex.EncodeToString(macBytes),
|
"Grpc-Metadata-Macaroon+%s", hex.EncodeToString(macBytes),
|
||||||
))
|
))
|
||||||
c, err := openWebSocket(net.Alice, url, "POST", req, customHeader)
|
c, err := openWebSocket(alice, url, "POST", req, customHeader)
|
||||||
require.Nil(ht.t, err, "websocket")
|
require.Nil(ht, err, "websocket")
|
||||||
defer func() {
|
defer func() {
|
||||||
err := c.WriteMessage(websocket.CloseMessage, closeMsg)
|
err := c.WriteMessage(websocket.CloseMessage, closeMsg)
|
||||||
require.NoError(ht.t, err)
|
require.NoError(ht, err)
|
||||||
_ = c.Close()
|
_ = c.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -394,52 +391,49 @@ func wsTestCaseSubscriptionMacaroon(ht *harnessTest,
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// Mine a block and make sure we get a message for it.
|
// Mine a block and make sure we get a message for it.
|
||||||
blockHashes, err := net.Miner.Client.Generate(1)
|
blockHashes := ht.Miner.GenerateBlocks(1)
|
||||||
require.Nil(ht.t, err, "generate blocks")
|
|
||||||
assert.Equal(ht.t, 1, len(blockHashes), "num blocks")
|
|
||||||
select {
|
select {
|
||||||
case msg := <-msgChan:
|
case msg := <-msgChan:
|
||||||
assert.Equal(
|
require.Equal(
|
||||||
ht.t, blockHashes[0].CloneBytes(), msg.Hash,
|
ht, blockHashes[0].CloneBytes(), msg.Hash,
|
||||||
"block hash",
|
"block hash",
|
||||||
)
|
)
|
||||||
|
|
||||||
case err := <-errChan:
|
case err := <-errChan:
|
||||||
ht.t.Fatalf("Received error from WS: %v", err)
|
ht.Fatalf("Received error from WS: %v", err)
|
||||||
|
|
||||||
case <-timeout:
|
case <-timeout:
|
||||||
ht.t.Fatalf("Timeout before message was received")
|
ht.Fatalf("Timeout before message was received")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func wsTestCaseBiDirectionalSubscription(ht *harnessTest,
|
func wsTestCaseBiDirectionalSubscription(ht *lntemp.HarnessTest) {
|
||||||
net *lntest.NetworkHarness) {
|
|
||||||
|
|
||||||
initialRequest := &lnrpc.ChannelAcceptResponse{}
|
initialRequest := &lnrpc.ChannelAcceptResponse{}
|
||||||
url := "/v1/channels/acceptor"
|
url := "/v1/channels/acceptor"
|
||||||
|
|
||||||
// This time we send the macaroon in the special header
|
// This time we send the macaroon in the special header
|
||||||
// Sec-Websocket-Protocol which is the only header field available to
|
// Sec-Websocket-Protocol which is the only header field available to
|
||||||
// browsers when opening a WebSocket.
|
// browsers when opening a WebSocket.
|
||||||
mac, err := net.Alice.ReadMacaroon(
|
alice := ht.Alice
|
||||||
net.Alice.AdminMacPath(), defaultTimeout,
|
mac, err := alice.ReadMacaroon(
|
||||||
|
alice.Cfg.AdminMacPath, defaultTimeout,
|
||||||
)
|
)
|
||||||
require.NoError(ht.t, err, "read admin mac")
|
require.NoError(ht, err, "read admin mac")
|
||||||
macBytes, err := mac.MarshalBinary()
|
macBytes, err := mac.MarshalBinary()
|
||||||
require.NoError(ht.t, err, "marshal admin mac")
|
require.NoError(ht, err, "marshal admin mac")
|
||||||
|
|
||||||
customHeader := make(http.Header)
|
customHeader := make(http.Header)
|
||||||
customHeader.Set(lnrpc.HeaderWebSocketProtocol, fmt.Sprintf(
|
customHeader.Set(lnrpc.HeaderWebSocketProtocol, fmt.Sprintf(
|
||||||
"Grpc-Metadata-Macaroon+%s", hex.EncodeToString(macBytes),
|
"Grpc-Metadata-Macaroon+%s", hex.EncodeToString(macBytes),
|
||||||
))
|
))
|
||||||
conn, err := openWebSocket(
|
conn, err := openWebSocket(
|
||||||
net.Alice, url, "POST", initialRequest, customHeader,
|
alice, url, "POST", initialRequest, customHeader,
|
||||||
)
|
)
|
||||||
require.Nil(ht.t, err, "websocket")
|
require.Nil(ht, err, "websocket")
|
||||||
defer func() {
|
defer func() {
|
||||||
err := conn.WriteMessage(websocket.CloseMessage, closeMsg)
|
err := conn.WriteMessage(websocket.CloseMessage, closeMsg)
|
||||||
_ = conn.Close()
|
_ = conn.Close()
|
||||||
require.NoError(ht.t, err)
|
require.NoError(ht, err)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Buffer the message channel to make sure we're always blocking on
|
// Buffer the message channel to make sure we're always blocking on
|
||||||
@@ -528,29 +522,30 @@ func wsTestCaseBiDirectionalSubscription(ht *harnessTest,
|
|||||||
|
|
||||||
// Before we start opening channels, make sure the two nodes are
|
// Before we start opening channels, make sure the two nodes are
|
||||||
// connected.
|
// connected.
|
||||||
net.EnsureConnected(ht.t, net.Alice, net.Bob)
|
bob := ht.Bob
|
||||||
|
ht.EnsureConnected(alice, bob)
|
||||||
|
|
||||||
// Open 3 channels to make sure multiple requests and responses can be
|
// Open 3 channels to make sure multiple requests and responses can be
|
||||||
// sent over the web socket.
|
// sent over the web socket.
|
||||||
const numChannels = 3
|
const numChannels = 3
|
||||||
for i := 0; i < numChannels; i++ {
|
for i := 0; i < numChannels; i++ {
|
||||||
openChannelAndAssert(
|
chanPoint := ht.OpenChannel(
|
||||||
ht, net, net.Bob, net.Alice,
|
bob, alice, lntemp.OpenChannelParams{Amt: 500000},
|
||||||
lntest.OpenChannelParams{Amt: 500000},
|
|
||||||
)
|
)
|
||||||
|
defer ht.CloseChannel(bob, chanPoint)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case <-msgChan:
|
case <-msgChan:
|
||||||
case err := <-errChan:
|
case err := <-errChan:
|
||||||
ht.t.Fatalf("Received error from WS: %v", err)
|
ht.Fatalf("Received error from WS: %v", err)
|
||||||
|
|
||||||
case <-timeout:
|
case <-timeout:
|
||||||
ht.t.Fatalf("Timeout before message was received")
|
ht.Fatalf("Timeout before message was received")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func wsTestPingPongTimeout(ht *harnessTest, net *lntest.NetworkHarness) {
|
func wsTestPingPongTimeout(ht *lntemp.HarnessTest) {
|
||||||
initialRequest := &lnrpc.InvoiceSubscription{
|
initialRequest := &lnrpc.InvoiceSubscription{
|
||||||
AddIndex: 1, SettleIndex: 1,
|
AddIndex: 1, SettleIndex: 1,
|
||||||
}
|
}
|
||||||
@@ -559,25 +554,26 @@ func wsTestPingPongTimeout(ht *harnessTest, net *lntest.NetworkHarness) {
|
|||||||
// This time we send the macaroon in the special header
|
// This time we send the macaroon in the special header
|
||||||
// Sec-Websocket-Protocol which is the only header field available to
|
// Sec-Websocket-Protocol which is the only header field available to
|
||||||
// browsers when opening a WebSocket.
|
// browsers when opening a WebSocket.
|
||||||
mac, err := net.Alice.ReadMacaroon(
|
alice := ht.Alice
|
||||||
net.Alice.AdminMacPath(), defaultTimeout,
|
mac, err := alice.ReadMacaroon(
|
||||||
|
alice.Cfg.AdminMacPath, defaultTimeout,
|
||||||
)
|
)
|
||||||
require.NoError(ht.t, err, "read admin mac")
|
require.NoError(ht, err, "read admin mac")
|
||||||
macBytes, err := mac.MarshalBinary()
|
macBytes, err := mac.MarshalBinary()
|
||||||
require.NoError(ht.t, err, "marshal admin mac")
|
require.NoError(ht, err, "marshal admin mac")
|
||||||
|
|
||||||
customHeader := make(http.Header)
|
customHeader := make(http.Header)
|
||||||
customHeader.Set(lnrpc.HeaderWebSocketProtocol, fmt.Sprintf(
|
customHeader.Set(lnrpc.HeaderWebSocketProtocol, fmt.Sprintf(
|
||||||
"Grpc-Metadata-Macaroon+%s", hex.EncodeToString(macBytes),
|
"Grpc-Metadata-Macaroon+%s", hex.EncodeToString(macBytes),
|
||||||
))
|
))
|
||||||
conn, err := openWebSocket(
|
conn, err := openWebSocket(
|
||||||
net.Alice, url, "GET", initialRequest, customHeader,
|
alice, url, "GET", initialRequest, customHeader,
|
||||||
)
|
)
|
||||||
require.Nil(ht.t, err, "websocket")
|
require.Nil(ht, err, "websocket")
|
||||||
defer func() {
|
defer func() {
|
||||||
err := conn.WriteMessage(websocket.CloseMessage, closeMsg)
|
err := conn.WriteMessage(websocket.CloseMessage, closeMsg)
|
||||||
_ = conn.Close()
|
_ = conn.Close()
|
||||||
require.NoError(ht.t, err)
|
require.NoError(ht, err)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// We want to be able to read invoices for a long time, making sure we
|
// We want to be able to read invoices for a long time, making sure we
|
||||||
@@ -650,27 +646,26 @@ func wsTestPingPongTimeout(ht *harnessTest, net *lntest.NetworkHarness) {
|
|||||||
|
|
||||||
// Let's create five invoices and wait for them to arrive. We'll wait
|
// Let's create five invoices and wait for them to arrive. We'll wait
|
||||||
// for at least one ping/pong cycle between each invoice.
|
// for at least one ping/pong cycle between each invoice.
|
||||||
ctxb := context.Background()
|
|
||||||
const numInvoices = 5
|
const numInvoices = 5
|
||||||
const value = 123
|
const value = 123
|
||||||
const memo = "websocket"
|
const memo = "websocket"
|
||||||
for i := 0; i < numInvoices; i++ {
|
for i := 0; i < numInvoices; i++ {
|
||||||
_, err := net.Alice.AddInvoice(ctxb, &lnrpc.Invoice{
|
invoice := &lnrpc.Invoice{
|
||||||
Value: value,
|
Value: value,
|
||||||
Memo: memo,
|
Memo: memo,
|
||||||
})
|
}
|
||||||
require.NoError(ht.t, err)
|
alice.RPC.AddInvoice(invoice)
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case streamMsg := <-invoices:
|
case streamMsg := <-invoices:
|
||||||
require.Equal(ht.t, int64(value), streamMsg.Value)
|
require.Equal(ht, int64(value), streamMsg.Value)
|
||||||
require.Equal(ht.t, memo, streamMsg.Memo)
|
require.Equal(ht, memo, streamMsg.Memo)
|
||||||
|
|
||||||
case err := <-errChan:
|
case err := <-errChan:
|
||||||
require.Fail(ht.t, "Error reading invoice: %v", err)
|
require.Fail(ht, "Error reading invoice: %v", err)
|
||||||
|
|
||||||
case <-timeout:
|
case <-timeout:
|
||||||
require.Fail(ht.t, "No invoice msg received in time")
|
require.Fail(ht, "No invoice msg received in time")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's wait for at least a whole ping/pong cycle to happen, so
|
// Let's wait for at least a whole ping/pong cycle to happen, so
|
||||||
@@ -683,7 +678,7 @@ func wsTestPingPongTimeout(ht *harnessTest, net *lntest.NetworkHarness) {
|
|||||||
// invokeGET calls the given URL with the GET method and appropriate macaroon
|
// invokeGET calls the given URL with the GET method and appropriate macaroon
|
||||||
// header fields then tries to unmarshal the response into the given response
|
// header fields then tries to unmarshal the response into the given response
|
||||||
// proto message.
|
// proto message.
|
||||||
func invokeGET(node *lntest.HarnessNode, url string, resp proto.Message) error {
|
func invokeGET(node *node.HarnessNode, url string, resp proto.Message) error {
|
||||||
_, rawResp, err := makeRequest(node, url, "GET", nil, nil)
|
_, rawResp, err := makeRequest(node, url, "GET", nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -695,7 +690,7 @@ func invokeGET(node *lntest.HarnessNode, url string, resp proto.Message) error {
|
|||||||
// invokePOST calls the given URL with the POST method, request body and
|
// invokePOST calls the given URL with the POST method, request body and
|
||||||
// appropriate macaroon header fields then tries to unmarshal the response into
|
// appropriate macaroon header fields then tries to unmarshal the response into
|
||||||
// the given response proto message.
|
// the given response proto message.
|
||||||
func invokePOST(node *lntest.HarnessNode, url string, req,
|
func invokePOST(node *node.HarnessNode, url string, req,
|
||||||
resp proto.Message) error {
|
resp proto.Message) error {
|
||||||
|
|
||||||
// Marshal the request to JSON using the jsonpb marshaler to get correct
|
// Marshal the request to JSON using the jsonpb marshaler to get correct
|
||||||
@@ -715,7 +710,7 @@ func invokePOST(node *lntest.HarnessNode, url string, req,
|
|||||||
|
|
||||||
// makeRequest calls the given URL with the given method, request body and
|
// makeRequest calls the given URL with the given method, request body and
|
||||||
// appropriate macaroon header fields and returns the raw response body.
|
// appropriate macaroon header fields and returns the raw response body.
|
||||||
func makeRequest(node *lntest.HarnessNode, url, method string,
|
func makeRequest(node *node.HarnessNode, url, method string,
|
||||||
request io.Reader, additionalHeaders http.Header) (http.Header, []byte,
|
request io.Reader, additionalHeaders http.Header) (http.Header, []byte,
|
||||||
error) {
|
error) {
|
||||||
|
|
||||||
@@ -748,7 +743,7 @@ func makeRequest(node *lntest.HarnessNode, url, method string,
|
|||||||
|
|
||||||
// openWebSocket opens a new WebSocket connection to the given URL with the
|
// openWebSocket opens a new WebSocket connection to the given URL with the
|
||||||
// appropriate macaroon headers and sends the request message over the socket.
|
// appropriate macaroon headers and sends the request message over the socket.
|
||||||
func openWebSocket(node *lntest.HarnessNode, url, method string,
|
func openWebSocket(node *node.HarnessNode, url, method string,
|
||||||
req proto.Message, customHeader http.Header) (*websocket.Conn, error) {
|
req proto.Message, customHeader http.Header) (*websocket.Conn, error) {
|
||||||
|
|
||||||
// Prepare our macaroon headers and assemble the full URL from the
|
// Prepare our macaroon headers and assemble the full URL from the
|
||||||
@@ -785,8 +780,8 @@ func openWebSocket(node *lntest.HarnessNode, url, method string,
|
|||||||
|
|
||||||
// addAdminMacaroon reads the admin macaroon from the node and appends it to
|
// addAdminMacaroon reads the admin macaroon from the node and appends it to
|
||||||
// the HTTP header fields.
|
// the HTTP header fields.
|
||||||
func addAdminMacaroon(node *lntest.HarnessNode, header http.Header) error {
|
func addAdminMacaroon(node *node.HarnessNode, header http.Header) error {
|
||||||
mac, err := node.ReadMacaroon(node.AdminMacPath(), defaultTimeout)
|
mac, err := node.ReadMacaroon(node.Cfg.AdminMacPath, defaultTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,10 +146,6 @@ var allTestCases = []*testCase{
|
|||||||
name: "send multi path payment",
|
name: "send multi path payment",
|
||||||
test: testSendMultiPathPayment,
|
test: testSendMultiPathPayment,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "REST API",
|
|
||||||
test: testRestAPI,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "forward interceptor",
|
name: "forward interceptor",
|
||||||
test: testForwardInterceptorBasic,
|
test: testForwardInterceptorBasic,
|
||||||
|
|||||||
Reference in new issue
Block a user