From a6f653aac4ade5da82b8e733981162450e7fff0c Mon Sep 17 00:00:00 2001 From: aya Date: Sat, 1 Feb 2025 15:02:12 +0200 Subject: [PATCH] Add relay tests --- testlibs/{ => src}/main-wrappers.go | 35 +++++++- testlibs/src/relay_wrapper.go | 88 +++++++++++++++++++ testlibs/src/store_wrappers.go | 0 testlibs/utilities/logging.go | 47 ++++++++++ testlibs/utilities/test_data.go | 10 +++ testlibs/utilities/utils.go | 63 +++++++++++++ testlibs/waku-go-tests/nodes_basic_test.go | 35 ++++++++ .../waku-go-tests/peers_connection_test.go | 76 ++++++++++++++++ testlibs/waku-go-tests/relay_test.go | 50 +++++++++++ 9 files changed, 403 insertions(+), 1 deletion(-) rename testlibs/{ => src}/main-wrappers.go (90%) create mode 100644 testlibs/src/relay_wrapper.go create mode 100644 testlibs/src/store_wrappers.go create mode 100644 testlibs/utilities/logging.go create mode 100644 testlibs/utilities/test_data.go create mode 100644 testlibs/utilities/utils.go create mode 100644 testlibs/waku-go-tests/nodes_basic_test.go create mode 100644 testlibs/waku-go-tests/peers_connection_test.go create mode 100644 testlibs/waku-go-tests/relay_test.go diff --git a/testlibs/main-wrappers.go b/testlibs/src/main-wrappers.go similarity index 90% rename from testlibs/main-wrappers.go rename to testlibs/src/main-wrappers.go index 05f16a7..86204bc 100644 --- a/testlibs/main-wrappers.go +++ b/testlibs/src/main-wrappers.go @@ -3,12 +3,14 @@ package testlibs import ( "context" "errors" + "time" "github.com/libp2p/go-libp2p/core/peer" - + "github.com/waku-org/go-waku/waku/v2/protocol/pb" utilities "github.com/waku-org/waku-go-bindings/testlibs/utilities" "github.com/waku-org/waku-go-bindings/waku" "go.uber.org/zap" + "google.golang.org/protobuf/proto" ) type WakuNodeWrapper struct { @@ -346,3 +348,34 @@ func (wrapper *WakuNodeWrapper) Wrappers_StopDiscV5() error { utilities.Debug("Successfully stopped Discovery V5") return nil } + +func (wrapper *WakuNodeWrapper) Wrappers_Version() (string, error) { + if err := utilities.CheckWakuNodeNull(nil, wrapper.WakuNode); err != nil { + utilities.Error("cannot get version; node is nil", zap.Error(err)) + return "", err + } + + utilities.Debug("Attempting to retrieve Waku node version") + version, err := wrapper.WakuNode.Version() + if err != nil { + utilities.Error("failed to retrieve Waku node version", zap.Error(err)) + return "", err + } + + utilities.Debug("Successfully retrieved Waku node version", zap.String("version", version)) + return version, nil +} + +func (wrapper *WakuNodeWrapper) Wrappers_CreateMessage() *pb.WakuMessage { + utilities.Debug("Creating a WakuMessage with valid format and payload") + + message := &pb.WakuMessage{ + Payload: []byte("This is a valid Waku message payload"), + ContentTopic: "test-content-topic", + Version: proto.Uint32(0), + Timestamp: proto.Int64(time.Now().UnixNano()), + } + + utilities.Debug("Successfully created a valid WakuMessage") + return message +} diff --git a/testlibs/src/relay_wrapper.go b/testlibs/src/relay_wrapper.go new file mode 100644 index 0000000..7f3d059 --- /dev/null +++ b/testlibs/src/relay_wrapper.go @@ -0,0 +1,88 @@ +package testlibs + +import ( + "context" + "errors" + "time" + + "github.com/waku-org/go-waku/waku/v2/protocol/pb" + utilities "github.com/waku-org/waku-go-bindings/testlibs/utilities" + "github.com/waku-org/waku-go-bindings/waku/common" + "go.uber.org/zap" +) + +func (wrapper *WakuNodeWrapper) Wrappers_RelaySubscribe(pubsubTopic string) error { + utilities.Debug("Attempting to subscribe to relay topic", zap.String("topic", pubsubTopic)) + + if err := utilities.CheckWakuNodeNull(nil, wrapper.WakuNode); err != nil { + utilities.Error("Cannot subscribe; node is nil", zap.Error(err)) + return err + } + + err := wrapper.WakuNode.RelaySubscribe(pubsubTopic) + if err != nil { + utilities.Error("Failed to subscribe to relay topic", zap.Error(err)) + return err + } + + // Ensure the subscription happened by checking the number of connected relay peers + numRelayPeers, err := wrapper.Wrappers_GetNumConnectedRelayPeers(pubsubTopic) + if err != nil || numRelayPeers == 0 { + utilities.Error("Subscription verification failed: no connected relay peers found", zap.Error(err)) + return errors.New("subscription verification failed: no connected relay peers") + } + + utilities.Debug("Successfully subscribed to relay topic", zap.String("topic", pubsubTopic)) + return nil +} + +func (wrapper *WakuNodeWrapper) Wrappers_RelayUnsubscribe(pubsubTopic string) error { + utilities.Debug("Attempting to unsubscribe from relay topic", zap.String("topic", pubsubTopic)) + + if err := utilities.CheckWakuNodeNull(nil, wrapper.WakuNode); err != nil { + utilities.Error("Cannot unsubscribe; node is nil", zap.Error(err)) + return err + } + + err := wrapper.WakuNode.RelayUnsubscribe(pubsubTopic) + if err != nil { + utilities.Error("Failed to unsubscribe from relay topic", zap.Error(err)) + return err + } + + // Ensure the unsubscription happened by verifying the relay peers count + numRelayPeers, err := wrapper.Wrappers_GetNumConnectedRelayPeers(pubsubTopic) + if err != nil { + utilities.Error("Failed to verify unsubscription from relay topic", zap.Error(err)) + return err + } + if numRelayPeers > 0 { + utilities.Error("Unsubscription verification failed: relay peers still connected", zap.Int("relayPeers", numRelayPeers)) + return errors.New("unsubscription verification failed: relay peers still connected") + } + + utilities.Debug("Successfully unsubscribed from relay topic", zap.String("topic", pubsubTopic)) + return nil +} + +func (wrapper *WakuNodeWrapper) Wrappers_RelayPublish(pubsubTopic string, message *pb.WakuMessage) (common.MessageHash, error) { + if err := utilities.CheckWakuNodeNull(nil, wrapper.WakuNode); err != nil { + utilities.Error("cannot publish message; node is nil", zap.Error(err)) + return "", err + } + + // Handling context internally with a timeout + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + utilities.Debug("Attempting to publish message via relay", zap.String("pubsubTopic", pubsubTopic)) + + msgHash, err := wrapper.WakuNode.RelayPublish(ctx, message, pubsubTopic) + if err != nil { + utilities.Error("failed to publish message via relay", zap.Error(err)) + return "", err + } + + utilities.Debug("Successfully published message via relay", zap.String("messageHash", msgHash.String())) + return msgHash, nil +} diff --git a/testlibs/src/store_wrappers.go b/testlibs/src/store_wrappers.go new file mode 100644 index 0000000..e69de29 diff --git a/testlibs/utilities/logging.go b/testlibs/utilities/logging.go new file mode 100644 index 0000000..f5c4f6c --- /dev/null +++ b/testlibs/utilities/logging.go @@ -0,0 +1,47 @@ +package utilities + +import ( + "go.uber.org/zap" +) + +var devLogger *zap.Logger + +func init() { + var err error + devLogger, err = zap.NewDevelopment() + if err != nil { + panic("Failed to create development logger: " + err.Error()) + } +} + +func Debug(msg string, fields ...zap.Field) { + devLogger.Debug(msg, fields...) +} + +func Info(msg string, fields ...zap.Field) { + devLogger.Info(msg, fields...) +} + +func Warn(msg string, fields ...zap.Field) { + devLogger.Warn(msg, fields...) +} + +func Error(msg string, fields ...zap.Field) { + devLogger.Error(msg, fields...) +} + +func DPanic(msg string, fields ...zap.Field) { + devLogger.DPanic(msg, fields...) +} + +func Panic(msg string, fields ...zap.Field) { + devLogger.Panic(msg, fields...) +} + +func Fatal(msg string, fields ...zap.Field) { + devLogger.Fatal(msg, fields...) +} + +func Sync() { + _ = devLogger.Sync() +} diff --git a/testlibs/utilities/test_data.go b/testlibs/utilities/test_data.go new file mode 100644 index 0000000..19d3556 --- /dev/null +++ b/testlibs/utilities/test_data.go @@ -0,0 +1,10 @@ +package utilities + +import ( + "time" +) + +var ConnectPeerTimeout = 10 * time.Second //default timeout for node to connect to another node + +var DefaultPubsubTopic = "/waku/2/rs/3/0" +var PubsubTopic1 = "/waku/2/rs/3/1" diff --git a/testlibs/utilities/utils.go b/testlibs/utilities/utils.go new file mode 100644 index 0000000..1da1e37 --- /dev/null +++ b/testlibs/utilities/utils.go @@ -0,0 +1,63 @@ +package utilities + +import ( + "math/rand" + "sync" + "time" + "errors" + "go.uber.org/zap" + "github.com/waku-org/waku-go-bindings/waku" +) + +var ( + MinPort = 1024 // Minimum allowable port (exported) + MaxPort = 65535 // Maximum allowable port (exported) + usedPorts = make(map[int]bool) // Tracks used ports (internal to package) + portsMutex sync.Mutex // Ensures thread-safe access to usedPorts +) + +// Default configuration values +var DefaultWakuConfig = &waku.WakuConfig{ + Relay: false, + LogLevel: "DEBUG", + Discv5Discovery: true, + ClusterID: 16, + Shards: []uint16{64}, + PeerExchange: false, + Store: false, + Filter: false, + Lightpush: false, +} + +// WakuConfigOption is a function that applies a change to a WakuConfig. +type WakuConfigOption func(*waku.WakuConfig) + + + +func GenerateUniquePort() int { + rng := rand.New(rand.NewSource(time.Now().UnixNano())) // Local RNG instance + + for { + port := rng.Intn(MaxPort-MinPort+1) + MinPort + + portsMutex.Lock() + if !usedPorts[port] { + usedPorts[port] = true + portsMutex.Unlock() + return port + } + portsMutex.Unlock() + } +} + + +func CheckWakuNodeNull(logger *zap.Logger, node interface{}) error { + if node == nil { + err := errors.New("WakuNode instance is nil") + if logger != nil { + logger.Error("WakuNode is nil", zap.Error(err)) + } + return err + } + return nil +} \ No newline at end of file diff --git a/testlibs/waku-go-tests/nodes_basic_test.go b/testlibs/waku-go-tests/nodes_basic_test.go new file mode 100644 index 0000000..a7b71c5 --- /dev/null +++ b/testlibs/waku-go-tests/nodes_basic_test.go @@ -0,0 +1,35 @@ +package waku_go_tests + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + testlibs "github.com/waku-org/waku-go-bindings/testlibs/src" + utilities "github.com/waku-org/waku-go-bindings/testlibs/utilities" + "go.uber.org/zap" +) + +func TestBasicWakuNodes(t *testing.T) { + utilities.Debug("Create logger instance") + logger, _ := zap.NewDevelopment() + + nodeCfg := *utilities.DefaultWakuConfig + nodeCfg.Relay = true + + utilities.Debug("Starting the WakuNodeWrapper") + node, err := testlibs.Wrappers_StartWakuNode(&nodeCfg, logger.Named("node")) + require.NoError(t, err, "Failed to create the WakuNodeWrapper") + + // Use defer to ensure proper cleanup + defer func() { + utilities.Debug("Stopping and destroying Node") + node.Wrappers_StopAndDestroy() + }() + utilities.Debug("Successfully created the WakuNodeWrapper") + + time.Sleep(2 * time.Second) + + // No need for another StopAndDestroy here, defer already handles cleanup + utilities.Debug("Test completed successfully") +} diff --git a/testlibs/waku-go-tests/peers_connection_test.go b/testlibs/waku-go-tests/peers_connection_test.go new file mode 100644 index 0000000..e3fa985 --- /dev/null +++ b/testlibs/waku-go-tests/peers_connection_test.go @@ -0,0 +1,76 @@ +package waku_go_tests + +import ( + "testing" + "time" + + "github.com/stretchr/testify/require" + testlibs "github.com/waku-org/waku-go-bindings/testlibs/src" + utilities "github.com/waku-org/waku-go-bindings/testlibs/utilities" + "go.uber.org/zap" +) + +// test node connect & disconnect peers +func TestDisconnectPeerNodes(t *testing.T) { + logger, err := zap.NewDevelopment() + require.NoError(t, err) + + // Create Node A + nodeA, err := testlibs.Wrappers_StartWakuNode(nil, logger.Named("nodeA")) + require.NoError(t, err) + defer nodeA.Wrappers_StopAndDestroy() + + // Create Node B + nodeB, err := testlibs.Wrappers_StartWakuNode(nil, logger.Named("nodeB")) + require.NoError(t, err) + defer nodeB.Wrappers_StopAndDestroy() + + // Connect Node A to Node B + err = nodeA.Wrappers_ConnectPeer(nodeB) + require.NoError(t, err, "failed to connect nodes") + + // Wait for 3 seconds + time.Sleep(3 * time.Second) + + // Disconnect Node A from Node B + err = nodeA.Wrappers_DisconnectPeer(nodeB) + require.NoError(t, err, "failed to disconnect nodes") +} + +func TestConnectMultipleNodesToSingleNode(t *testing.T) { + logger, err := zap.NewDevelopment() + require.NoError(t, err) + + utilities.Debug("Starting test to connect multiple nodes to a single node") + utilities.Debug("Create 3 nodes") + node1, err := testlibs.Wrappers_StartWakuNode(nil, logger.Named("Node1")) + require.NoError(t, err) + defer func() { + utilities.Debug("Stopping and destroying Node 1") + node1.Wrappers_StopAndDestroy() + }() + + node2, err := testlibs.Wrappers_StartWakuNode(nil, logger.Named("Node2")) + require.NoError(t, err) + defer func() { + utilities.Debug("Stopping and destroying Node 2") + node2.Wrappers_StopAndDestroy() + }() + + node3, err := testlibs.Wrappers_StartWakuNode(nil, logger.Named("Node3")) + require.NoError(t, err) + defer func() { + utilities.Debug("Stopping and destroying Node 3") + node3.Wrappers_StopAndDestroy() + }() + + utilities.Debug("Connecting Node 2 to Node 1") + err = node2.Wrappers_ConnectPeer(node1) + require.NoError(t, err) + + utilities.Debug("Connecting Node 3 to Node 1") + err = node3.Wrappers_ConnectPeer(node1) + require.NoError(t, err) + + utilities.Debug("Test completed successfully: multiple nodes connected to a single node") +} diff --git a/testlibs/waku-go-tests/relay_test.go b/testlibs/waku-go-tests/relay_test.go new file mode 100644 index 0000000..52828b7 --- /dev/null +++ b/testlibs/waku-go-tests/relay_test.go @@ -0,0 +1,50 @@ +package waku_go_tests + +import ( + "testing" + + "github.com/stretchr/testify/require" + testlibs "github.com/waku-org/waku-go-bindings/testlibs/src" + utilities "github.com/waku-org/waku-go-bindings/testlibs/utilities" + "go.uber.org/zap" +) + +func TestRelaySubscribeToDefaultTopic(t *testing.T) { + logger, err := zap.NewDevelopment() + require.NoError(t, err) + + utilities.Debug("Starting test to verify relay subscription to the default pubsub topic") + + // Define the configuration with relay = true + wakuConfig := *utilities.DefaultWakuConfig + wakuConfig.Relay = true + + utilities.Debug("Creating a Waku node with relay enabled") + node, err := testlibs.Wrappers_StartWakuNode(&wakuConfig, logger.Named("TestNode")) + require.NoError(t, err) + defer func() { + utilities.Debug("Stopping and destroying the Waku node") + node.Wrappers_StopAndDestroy() + }() + + defaultPubsubTopic := utilities.DefaultPubsubTopic + utilities.Debug("Default pubsub topic retrieved", zap.String("topic", defaultPubsubTopic)) + + utilities.Debug("Fetching number of connected relay peers before subscription", zap.String("topic", defaultPubsubTopic)) + numPeersBefore, err := node.Wrappers_GetNumConnectedRelayPeers(defaultPubsubTopic) + require.NoError(t, err) + utilities.Debug("Number of connected relay peers before subscription", zap.Int("count", numPeersBefore)) + + utilities.Debug("Attempting to subscribe to the default pubsub topic", zap.String("topic", defaultPubsubTopic)) + err = node.Wrappers_RelaySubscribe(defaultPubsubTopic) + require.NoError(t, err) + + utilities.Debug("Fetching number of connected relay peers after subscription", zap.String("topic", defaultPubsubTopic)) + numPeersAfter, err := node.Wrappers_GetNumConnectedRelayPeers(defaultPubsubTopic) + require.NoError(t, err) + utilities.Debug("Number of connected relay peers after subscription", zap.Int("count", numPeersAfter)) + + require.Greater(t, numPeersAfter, numPeersBefore, "Number of connected relay peers should increase after subscription") + + utilities.Debug("Test successfully verified subscription to the default pubsub topic", zap.String("topic", defaultPubsubTopic)) +}