611 lines
20 KiB
Go
611 lines
20 KiB
Go
package dns
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"sync/atomic"
|
|
"testing"
|
|
)
|
|
|
|
func TestMainchainClientGetsAliasDetailsAndParsesHNSComments(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
|
|
var payload struct {
|
|
Method string `json:"method"`
|
|
}
|
|
if err := json.NewDecoder(request.Body).Decode(&payload); err != nil {
|
|
t.Fatalf("unexpected request payload: %v", err)
|
|
}
|
|
if payload.Method != "get_all_alias_details" {
|
|
t.Fatalf("expected method get_all_alias_details, got %s", payload.Method)
|
|
}
|
|
|
|
responseWriter.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": []any{
|
|
map[string]any{
|
|
"name": "gateway",
|
|
"comment": "gateway alias hns=gateway.charon.lthn",
|
|
},
|
|
map[string]any{
|
|
"hns": "node.charon.lthn",
|
|
"name": "node",
|
|
},
|
|
},
|
|
})
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewMainchainAliasClient(MainchainClientOptions{
|
|
URL: server.URL,
|
|
})
|
|
|
|
aliases, err := client.GetAllAliasDetails(context.Background())
|
|
if err != nil {
|
|
t.Fatalf("unexpected get_all_alias_details error: %v", err)
|
|
}
|
|
if len(aliases) != 2 {
|
|
t.Fatalf("expected 2 aliases, got %d", len(aliases))
|
|
}
|
|
if aliases[0] != "gateway.charon.lthn" || aliases[1] != "node.charon.lthn" {
|
|
t.Fatalf("unexpected aliases: %#v", aliases)
|
|
}
|
|
}
|
|
|
|
func TestNewMainchainAliasClientFromOptionsMatchesNewMainchainAliasClient(t *testing.T) {
|
|
clientFromOptions := NewMainchainAliasClientFromOptions(MainchainClientOptions{URL: "http://127.0.0.1:14037"})
|
|
clientFromConfiguration := NewMainchainAliasClientFromConfiguration(MainchainAliasClientConfiguration{URL: "http://127.0.0.1:14037"})
|
|
|
|
if clientFromOptions == nil || clientFromConfiguration == nil {
|
|
t.Fatal("expected explicit main-chain constructors to return clients")
|
|
}
|
|
if clientFromOptions.baseURL != clientFromConfiguration.baseURL {
|
|
t.Fatalf("expected explicit main-chain constructors to normalize the same base URL, got %q and %q", clientFromOptions.baseURL, clientFromConfiguration.baseURL)
|
|
}
|
|
}
|
|
|
|
func TestServiceDiscoverFromMainchainAliasesUsesMainchainThenHSD(t *testing.T) {
|
|
var chainCalls int32
|
|
var hsdTreeRootCalls int32
|
|
var hsdAliasCalls int32
|
|
|
|
server := httptest.NewServer(http.HandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
|
|
var payload struct {
|
|
Method string `json:"method"`
|
|
Params []any `json:"params"`
|
|
}
|
|
if err := json.NewDecoder(request.Body).Decode(&payload); err != nil {
|
|
t.Fatalf("unexpected request payload: %v", err)
|
|
}
|
|
|
|
switch payload.Method {
|
|
case "get_all_alias_details":
|
|
atomic.AddInt32(&chainCalls, 1)
|
|
responseWriter.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": []any{
|
|
map[string]any{
|
|
"hns": "gateway.charon.lthn",
|
|
},
|
|
map[string]any{
|
|
"hns": "node.charon.lthn",
|
|
},
|
|
},
|
|
})
|
|
case "getblockchaininfo":
|
|
atomic.AddInt32(&hsdTreeRootCalls, 1)
|
|
responseWriter.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": map[string]any{
|
|
"tree_root": "chain-root-1",
|
|
},
|
|
})
|
|
case "getnameresource":
|
|
atomic.AddInt32(&hsdAliasCalls, 1)
|
|
responseWriter.Header().Set("Content-Type", "application/json")
|
|
switch payload.Params[0] {
|
|
case "gateway.charon.lthn":
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": map[string]any{
|
|
"a": []string{"10.10.10.10"},
|
|
},
|
|
})
|
|
case "node.charon.lthn":
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": map[string]any{
|
|
"aaaa": []string{"2600:1f1c:7f0:4f01::2"},
|
|
},
|
|
})
|
|
default:
|
|
t.Fatalf("unexpected alias lookup: %#v", payload.Params)
|
|
}
|
|
default:
|
|
t.Fatalf("unexpected method: %s", payload.Method)
|
|
}
|
|
}))
|
|
defer server.Close()
|
|
|
|
service := NewService(ServiceOptions{})
|
|
chainClient := NewMainchainAliasClient(MainchainClientOptions{
|
|
URL: server.URL,
|
|
})
|
|
hsdClient := NewHSDClient(HSDClientOptions{
|
|
URL: server.URL,
|
|
})
|
|
|
|
if err := service.DiscoverFromMainchainAliases(context.Background(), chainClient, hsdClient); err != nil {
|
|
t.Fatalf("expected discover from mainchain aliases: %v", err)
|
|
}
|
|
|
|
gateway, ok := service.Resolve("gateway.charon.lthn")
|
|
if !ok || len(gateway.A) != 1 || gateway.A[0] != "10.10.10.10" {
|
|
t.Fatalf("expected gateway A record, got %#v (ok=%t)", gateway, ok)
|
|
}
|
|
node, ok := service.Resolve("node.charon.lthn")
|
|
if !ok || len(node.AAAA) != 1 || node.AAAA[0] != "2600:1f1c:7f0:4f01::2" {
|
|
t.Fatalf("expected node AAAA record, got %#v (ok=%t)", node, ok)
|
|
}
|
|
|
|
if chainCalls != 1 || hsdTreeRootCalls != 1 || hsdAliasCalls != 2 {
|
|
t.Fatalf("expected chain=1 tree-root=1 name-resource=2, got %d %d %d", chainCalls, hsdTreeRootCalls, hsdAliasCalls)
|
|
}
|
|
}
|
|
|
|
func TestServiceDiscoverFromMainchainAliasesFallsBackToConfiguredMainchainClient(t *testing.T) {
|
|
var chainCalls int32
|
|
var hsdTreeRootCalls int32
|
|
var hsdAliasCalls int32
|
|
|
|
server := httptest.NewServer(http.HandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
|
|
var payload struct {
|
|
Method string `json:"method"`
|
|
Params []any `json:"params"`
|
|
}
|
|
if err := json.NewDecoder(request.Body).Decode(&payload); err != nil {
|
|
t.Fatalf("unexpected request payload: %v", err)
|
|
}
|
|
|
|
switch payload.Method {
|
|
case "get_all_alias_details":
|
|
atomic.AddInt32(&chainCalls, 1)
|
|
responseWriter.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": []any{
|
|
map[string]any{
|
|
"hns": "gateway.charon.lthn",
|
|
},
|
|
},
|
|
})
|
|
case "getblockchaininfo":
|
|
atomic.AddInt32(&hsdTreeRootCalls, 1)
|
|
responseWriter.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": map[string]any{
|
|
"tree_root": "chain-root-1",
|
|
},
|
|
})
|
|
case "getnameresource":
|
|
atomic.AddInt32(&hsdAliasCalls, 1)
|
|
responseWriter.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": map[string]any{
|
|
"a": []string{"10.10.10.10"},
|
|
},
|
|
})
|
|
default:
|
|
t.Fatalf("unexpected method: %s", payload.Method)
|
|
}
|
|
}))
|
|
defer server.Close()
|
|
|
|
service := NewService(ServiceOptions{
|
|
MainchainAliasClient: NewMainchainAliasClient(MainchainClientOptions{
|
|
URL: server.URL,
|
|
}),
|
|
})
|
|
hsdClient := NewHSDClient(HSDClientOptions{
|
|
URL: server.URL,
|
|
})
|
|
|
|
if err := service.DiscoverFromMainchainAliases(context.Background(), nil, hsdClient); err != nil {
|
|
t.Fatalf("expected discover from configured mainchain client: %v", err)
|
|
}
|
|
|
|
record, ok := service.Resolve("gateway.charon.lthn")
|
|
if !ok || len(record.A) != 1 || record.A[0] != "10.10.10.10" {
|
|
t.Fatalf("expected gateway A record from configured client, got %#v (ok=%t)", record, ok)
|
|
}
|
|
|
|
if atomic.LoadInt32(&chainCalls) != 1 || atomic.LoadInt32(&hsdTreeRootCalls) != 1 || atomic.LoadInt32(&hsdAliasCalls) != 1 {
|
|
t.Fatalf(
|
|
"expected chain=1 tree-root=1 name-resource=1, got %d %d %d",
|
|
atomic.LoadInt32(&chainCalls),
|
|
atomic.LoadInt32(&hsdTreeRootCalls),
|
|
atomic.LoadInt32(&hsdAliasCalls),
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestServiceDiscoverFromMainchainAliasesUsesActionDiscoverer(t *testing.T) {
|
|
var treeRootCalls int32
|
|
var nameResourceCalls int32
|
|
|
|
server := httptest.NewServer(http.HandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
|
|
var payload struct {
|
|
Method string `json:"method"`
|
|
Params []any `json:"params"`
|
|
}
|
|
if err := json.NewDecoder(request.Body).Decode(&payload); err != nil {
|
|
t.Fatalf("unexpected request payload: %v", err)
|
|
}
|
|
|
|
switch payload.Method {
|
|
case "getblockchaininfo":
|
|
atomic.AddInt32(&treeRootCalls, 1)
|
|
responseWriter.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": map[string]any{
|
|
"tree_root": "chain-root-1",
|
|
},
|
|
})
|
|
case "getnameresource":
|
|
atomic.AddInt32(&nameResourceCalls, 1)
|
|
switch payload.Params[0] {
|
|
case "gateway.charon.lthn":
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": map[string]any{
|
|
"a": []string{"10.10.10.10"},
|
|
},
|
|
})
|
|
case "node.charon.lthn":
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": map[string]any{
|
|
"aaaa": []string{"2600:1f1c:7f0:4f01::2"},
|
|
},
|
|
})
|
|
default:
|
|
t.Fatalf("unexpected alias lookup: %#v", payload.Params)
|
|
}
|
|
default:
|
|
t.Fatalf("unexpected method: %s", payload.Method)
|
|
}
|
|
}))
|
|
defer server.Close()
|
|
|
|
service := NewService(ServiceOptions{
|
|
ChainAliasDiscoverer: func(_ context.Context) ([]string, error) {
|
|
return []string{"gateway.charon.lthn", "node.charon.lthn"}, nil
|
|
},
|
|
})
|
|
hsdClient := NewHSDClient(HSDClientOptions{
|
|
URL: server.URL,
|
|
})
|
|
|
|
if err := service.DiscoverFromMainchainAliases(context.Background(), nil, hsdClient); err != nil {
|
|
t.Fatalf("expected discover from chain alias discoverer: %v", err)
|
|
}
|
|
|
|
gateway, ok := service.Resolve("gateway.charon.lthn")
|
|
if !ok || len(gateway.A) != 1 || gateway.A[0] != "10.10.10.10" {
|
|
t.Fatalf("expected gateway A record, got %#v (ok=%t)", gateway, ok)
|
|
}
|
|
node, ok := service.Resolve("node.charon.lthn")
|
|
if !ok || len(node.AAAA) != 1 || node.AAAA[0] != "2600:1f1c:7f0:4f01::2" {
|
|
t.Fatalf("expected node AAAA record, got %#v (ok=%t)", node, ok)
|
|
}
|
|
|
|
if atomic.LoadInt32(&treeRootCalls) != 1 || atomic.LoadInt32(&nameResourceCalls) != 2 {
|
|
t.Fatalf("expected tree-root and name-resource calls, got treeRoot=%d nameResource=%d", atomic.LoadInt32(&treeRootCalls), atomic.LoadInt32(&nameResourceCalls))
|
|
}
|
|
}
|
|
|
|
func TestServiceDiscoverFromMainchainAliasesFallsBackToFallbackChainAliasDiscoverer(t *testing.T) {
|
|
var treeRootCalls int32
|
|
var nameResourceCalls int32
|
|
|
|
server := httptest.NewServer(http.HandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
|
|
var payload struct {
|
|
Method string `json:"method"`
|
|
Params []any `json:"params"`
|
|
}
|
|
if err := json.NewDecoder(request.Body).Decode(&payload); err != nil {
|
|
t.Fatalf("unexpected request payload: %v", err)
|
|
}
|
|
|
|
switch payload.Method {
|
|
case "getblockchaininfo":
|
|
atomic.AddInt32(&treeRootCalls, 1)
|
|
responseWriter.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": map[string]any{
|
|
"tree_root": "chain-root-1",
|
|
},
|
|
})
|
|
case "getnameresource":
|
|
atomic.AddInt32(&nameResourceCalls, 1)
|
|
switch payload.Params[0] {
|
|
case "gateway.charon.lthn":
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": map[string]any{
|
|
"a": []string{"10.10.10.10"},
|
|
},
|
|
})
|
|
case "node.charon.lthn":
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": map[string]any{
|
|
"aaaa": []string{"2600:1f1c:7f0:4f01::2"},
|
|
},
|
|
})
|
|
default:
|
|
t.Fatalf("unexpected alias lookup: %#v", payload.Params)
|
|
}
|
|
default:
|
|
t.Fatalf("unexpected method: %s", payload.Method)
|
|
}
|
|
}))
|
|
defer server.Close()
|
|
|
|
service := NewService(ServiceOptions{
|
|
ChainAliasDiscoverer: func(_ context.Context) ([]string, error) {
|
|
return nil, errors.New("blockchain service unavailable")
|
|
},
|
|
FallbackChainAliasDiscoverer: func(_ context.Context) ([]string, error) {
|
|
return []string{"gateway.charon.lthn", "node.charon.lthn"}, nil
|
|
},
|
|
})
|
|
hsdClient := NewHSDClient(HSDClientOptions{
|
|
URL: server.URL,
|
|
})
|
|
|
|
if err := service.DiscoverFromMainchainAliases(context.Background(), nil, hsdClient); err != nil {
|
|
t.Fatalf("expected fallback discover from chain alias discoverer: %v", err)
|
|
}
|
|
|
|
gateway, ok := service.Resolve("gateway.charon.lthn")
|
|
if !ok || len(gateway.A) != 1 || gateway.A[0] != "10.10.10.10" {
|
|
t.Fatalf("expected gateway A record, got %#v (ok=%t)", gateway, ok)
|
|
}
|
|
node, ok := service.Resolve("node.charon.lthn")
|
|
if !ok || len(node.AAAA) != 1 || node.AAAA[0] != "2600:1f1c:7f0:4f01::2" {
|
|
t.Fatalf("expected node AAAA record, got %#v (ok=%t)", node, ok)
|
|
}
|
|
|
|
if atomic.LoadInt32(&treeRootCalls) != 1 || atomic.LoadInt32(&nameResourceCalls) != 2 {
|
|
t.Fatalf("expected fallback discovery to still trigger RPC calls, got treeRoot=%d nameResource=%d", atomic.LoadInt32(&treeRootCalls), atomic.LoadInt32(&nameResourceCalls))
|
|
}
|
|
}
|
|
|
|
func TestServiceDiscoverFromMainchainAliasesFallsBackToChainClientWhenFallbackChainAliasDiscovererFails(t *testing.T) {
|
|
var chainAliasCalls int32
|
|
var fallbackChainAliasCalls int32
|
|
var hsdTreeRootCalls int32
|
|
var hsdAliasCalls int32
|
|
|
|
server := httptest.NewServer(http.HandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
|
|
var payload struct {
|
|
Method string `json:"method"`
|
|
Params []any `json:"params"`
|
|
}
|
|
if err := json.NewDecoder(request.Body).Decode(&payload); err != nil {
|
|
t.Fatalf("unexpected request payload: %v", err)
|
|
}
|
|
|
|
switch payload.Method {
|
|
case "get_all_alias_details":
|
|
atomic.AddInt32(&chainAliasCalls, 1)
|
|
responseWriter.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": []any{
|
|
map[string]any{
|
|
"hns": "gateway.charon.lthn",
|
|
},
|
|
map[string]any{
|
|
"hns": "node.charon.lthn",
|
|
},
|
|
},
|
|
})
|
|
case "getblockchaininfo":
|
|
atomic.AddInt32(&hsdTreeRootCalls, 1)
|
|
responseWriter.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": map[string]any{
|
|
"tree_root": "chain-root-1",
|
|
},
|
|
})
|
|
case "getnameresource":
|
|
atomic.AddInt32(&hsdAliasCalls, 1)
|
|
switch payload.Params[0] {
|
|
case "gateway.charon.lthn":
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": map[string]any{
|
|
"a": []string{"10.10.10.10"},
|
|
},
|
|
})
|
|
case "node.charon.lthn":
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": map[string]any{
|
|
"aaaa": []string{"2600:1f1c:7f0:4f01::2"},
|
|
},
|
|
})
|
|
default:
|
|
t.Fatalf("unexpected alias lookup: %#v", payload.Params)
|
|
}
|
|
default:
|
|
t.Fatalf("unexpected method: %s", payload.Method)
|
|
}
|
|
}))
|
|
defer server.Close()
|
|
|
|
chainClient := NewMainchainAliasClient(MainchainClientOptions{
|
|
URL: server.URL,
|
|
})
|
|
hsdClient := NewHSDClient(HSDClientOptions{
|
|
URL: server.URL,
|
|
})
|
|
service := NewService(ServiceOptions{
|
|
ChainAliasDiscoverer: func(_ context.Context) ([]string, error) {
|
|
return nil, errors.New("blockchain service unavailable")
|
|
},
|
|
FallbackChainAliasDiscoverer: func(_ context.Context) ([]string, error) {
|
|
atomic.AddInt32(&fallbackChainAliasCalls, 1)
|
|
return nil, errors.New("fallback chain alias unavailable")
|
|
},
|
|
})
|
|
|
|
if err := service.DiscoverFromMainchainAliases(context.Background(), chainClient, hsdClient); err != nil {
|
|
t.Fatalf("expected fallback chain alias discoverer to fail over to chain client: %v", err)
|
|
}
|
|
|
|
gateway, ok := service.Resolve("gateway.charon.lthn")
|
|
if !ok || len(gateway.A) != 1 || gateway.A[0] != "10.10.10.10" {
|
|
t.Fatalf("expected gateway A record, got %#v (ok=%t)", gateway, ok)
|
|
}
|
|
node, ok := service.Resolve("node.charon.lthn")
|
|
if !ok || len(node.AAAA) != 1 || node.AAAA[0] != "2600:1f1c:7f0:4f01::2" {
|
|
t.Fatalf("expected node AAAA record, got %#v (ok=%t)", node, ok)
|
|
}
|
|
|
|
if atomic.LoadInt32(&fallbackChainAliasCalls) != 1 {
|
|
t.Fatalf("expected fallback chain alias discoverer to run and fail, got %d", atomic.LoadInt32(&fallbackChainAliasCalls))
|
|
}
|
|
if atomic.LoadInt32(&chainAliasCalls) != 1 {
|
|
t.Fatalf("expected chain alias client fallback to be used, got %d", atomic.LoadInt32(&chainAliasCalls))
|
|
}
|
|
if atomic.LoadInt32(&hsdTreeRootCalls) != 1 || atomic.LoadInt32(&hsdAliasCalls) != 2 {
|
|
t.Fatalf("expected fallback to still trigger RPC calls, got treeRoot=%d nameResource=%d", atomic.LoadInt32(&hsdTreeRootCalls), atomic.LoadInt32(&hsdAliasCalls))
|
|
}
|
|
}
|
|
|
|
func TestServiceDiscoverFromMainchainAliasesFallsBackToChainClientWhenPrimaryDiscovererFails(t *testing.T) {
|
|
var chainAliasCalls int32
|
|
var hsdTreeRootCalls int32
|
|
var hsdAliasCalls int32
|
|
|
|
server := httptest.NewServer(http.HandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) {
|
|
var payload struct {
|
|
Method string `json:"method"`
|
|
Params []any `json:"params"`
|
|
}
|
|
if err := json.NewDecoder(request.Body).Decode(&payload); err != nil {
|
|
t.Fatalf("unexpected request payload: %v", err)
|
|
}
|
|
|
|
switch payload.Method {
|
|
case "get_all_alias_details":
|
|
atomic.AddInt32(&chainAliasCalls, 1)
|
|
responseWriter.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": []any{
|
|
map[string]any{
|
|
"hns": "gateway.charon.lthn",
|
|
},
|
|
map[string]any{
|
|
"hns": "node.charon.lthn",
|
|
},
|
|
},
|
|
})
|
|
case "getblockchaininfo":
|
|
atomic.AddInt32(&hsdTreeRootCalls, 1)
|
|
responseWriter.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": map[string]any{
|
|
"tree_root": "chain-root-1",
|
|
},
|
|
})
|
|
case "getnameresource":
|
|
atomic.AddInt32(&hsdAliasCalls, 1)
|
|
responseWriter.Header().Set("Content-Type", "application/json")
|
|
switch payload.Params[0] {
|
|
case "gateway.charon.lthn":
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": map[string]any{
|
|
"a": []string{"10.10.10.10"},
|
|
},
|
|
})
|
|
case "node.charon.lthn":
|
|
_ = json.NewEncoder(responseWriter).Encode(map[string]any{
|
|
"result": map[string]any{
|
|
"aaaa": []string{"2600:1f1c:7f0:4f01::2"},
|
|
},
|
|
})
|
|
default:
|
|
t.Fatalf("unexpected alias lookup: %#v", payload.Params)
|
|
}
|
|
default:
|
|
t.Fatalf("unexpected method: %s", payload.Method)
|
|
}
|
|
}))
|
|
defer server.Close()
|
|
|
|
chainClient := NewMainchainAliasClient(MainchainClientOptions{
|
|
URL: server.URL,
|
|
})
|
|
hsdClient := NewHSDClient(HSDClientOptions{
|
|
URL: server.URL,
|
|
})
|
|
service := NewService(ServiceOptions{
|
|
ChainAliasDiscoverer: func(_ context.Context) ([]string, error) {
|
|
return nil, errors.New("blockchain service unavailable")
|
|
},
|
|
})
|
|
|
|
if err := service.DiscoverFromMainchainAliases(context.Background(), chainClient, hsdClient); err != nil {
|
|
t.Fatalf("expected chain alias discover fallback to chain client: %v", err)
|
|
}
|
|
|
|
gateway, ok := service.Resolve("gateway.charon.lthn")
|
|
if !ok || len(gateway.A) != 1 || gateway.A[0] != "10.10.10.10" {
|
|
t.Fatalf("expected gateway A record, got %#v (ok=%t)", gateway, ok)
|
|
}
|
|
node, ok := service.Resolve("node.charon.lthn")
|
|
if !ok || len(node.AAAA) != 1 || node.AAAA[0] != "2600:1f1c:7f0:4f01::2" {
|
|
t.Fatalf("expected node AAAA record, got %#v (ok=%t)", node, ok)
|
|
}
|
|
|
|
if atomic.LoadInt32(&chainAliasCalls) != 1 {
|
|
t.Fatalf("expected chain alias to be queried once, got %d", atomic.LoadInt32(&chainAliasCalls))
|
|
}
|
|
if atomic.LoadInt32(&hsdTreeRootCalls) != 1 || atomic.LoadInt32(&hsdAliasCalls) != 2 {
|
|
t.Fatalf("expected one tree-root and two name-resource RPC calls, got treeRoot=%d nameResource=%d", atomic.LoadInt32(&hsdTreeRootCalls), atomic.LoadInt32(&hsdAliasCalls))
|
|
}
|
|
}
|
|
|
|
func TestExtractAliasFromCommentParsesCaseInsensitiveHNSPrefix(t *testing.T) {
|
|
got := extractAliasFromComment("gateway alias HNS=gateway.charon.lthn")
|
|
if got != "gateway.charon.lthn" {
|
|
t.Fatalf("expected gateway.charon.lthn, got %s", got)
|
|
}
|
|
}
|
|
|
|
func TestNewServiceBuildsMainchainAliasClientWithHSDFallbackCredentials(t *testing.T) {
|
|
service := NewService(ServiceOptions{
|
|
MainchainURL: "http://127.0.0.1:14037",
|
|
HSDUsername: "mainchain-user",
|
|
HSDPassword: "mainchain-pass",
|
|
HSDApiKey: "ignored-token",
|
|
})
|
|
|
|
if service.mainchainAliasClient == nil {
|
|
t.Fatal("expected default mainchain alias client with fallback credentials")
|
|
}
|
|
if got := service.mainchainAliasClient.username; got != "mainchain-user" {
|
|
t.Fatalf("expected mainchain username to fall back to hsd username, got %q", got)
|
|
}
|
|
if got := service.mainchainAliasClient.password; got != "mainchain-pass" {
|
|
t.Fatalf("expected mainchain password to fall back to hsd password, got %q", got)
|
|
}
|
|
|
|
serviceFromToken := NewService(ServiceOptions{
|
|
MainchainURL: "http://127.0.0.1:14037",
|
|
HSDUsername: "token-user",
|
|
HSDApiKey: "token-pass",
|
|
})
|
|
if serviceFromToken.mainchainAliasClient == nil {
|
|
t.Fatal("expected default mainchain alias client with fallback token credentials")
|
|
}
|
|
if got := serviceFromToken.mainchainAliasClient.password; got != "token-pass" {
|
|
t.Fatalf("expected mainchain password to fall back to hsd api key token, got %q", got)
|
|
}
|
|
}
|