From e0b538fb8c9443e83c3084bd2a92dccbad15b4b6 Mon Sep 17 00:00:00 2001 From: Herbert Date: Tue, 3 Dec 2024 12:20:39 +0100 Subject: [PATCH] Add a test checking the support for subscribing to log events (#369) --- tests/integration_test_net.go | 25 ++++++++++------ tests/log_subscription_test.go | 52 ++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 tests/log_subscription_test.go diff --git a/tests/integration_test_net.go b/tests/integration_test_net.go index 9bd9c9ad0..154deb7de 100644 --- a/tests/integration_test_net.go +++ b/tests/integration_test_net.go @@ -58,10 +58,11 @@ import ( // integration test networks can also be used for automated integration and // regression tests for client code. type IntegrationTestNet struct { - directory string - done <-chan struct{} - validator Account - httpClientPort int + directory string + done <-chan struct{} + validator Account + httpPort int + wsPort int } func isPortFree(host string, port int) bool { @@ -226,11 +227,11 @@ func (n *IntegrationTestNet) start() error { // find free ports for the http-client, ws-client, and network interfaces var err error - n.httpClientPort, err = getFreePort() + n.httpPort, err = getFreePort() if err != nil { return err } - wsPort, err := getFreePort() + n.wsPort, err = getFreePort() if err != nil { return err } @@ -258,11 +259,11 @@ func (n *IntegrationTestNet) start() error { "--fakenet", "1/1", // http-client option - "--http", "--http.addr", "127.0.0.1", "--http.port", fmt.Sprint(n.httpClientPort), + "--http", "--http.addr", "127.0.0.1", "--http.port", fmt.Sprint(n.httpPort), "--http.api", "admin,eth,web3,net,txpool,ftm,trace,debug", // websocket-client options - "--ws", "--ws.addr", "127.0.0.1", "--ws.port", fmt.Sprint(wsPort), + "--ws", "--ws.addr", "127.0.0.1", "--ws.port", fmt.Sprint(n.wsPort), "--ws.api", "admin,eth,ftm", // net options @@ -470,7 +471,13 @@ func (n *IntegrationTestNet) GetTransactOptions(account *Account) (*bind.Transac // GetClient provides raw access to a fresh connection to the network. // The resulting client must be closed after use. func (n *IntegrationTestNet) GetClient() (*ethclient.Client, error) { - return ethclient.Dial(fmt.Sprintf("http://localhost:%d", n.httpClientPort)) + return ethclient.Dial(fmt.Sprintf("http://localhost:%d", n.httpPort)) +} + +// GetWebSocketClient provides raw access to a fresh connection to the network +// using the WebSocket protocol. The resulting client must be closed after use. +func (n *IntegrationTestNet) GetWebSocketClient() (*ethclient.Client, error) { + return ethclient.Dial(fmt.Sprintf("ws://localhost:%d", n.wsPort)) } // RestartWithExportImport stops the network, exports the genesis file, cleans the diff --git a/tests/log_subscription_test.go b/tests/log_subscription_test.go new file mode 100644 index 000000000..e445eac6f --- /dev/null +++ b/tests/log_subscription_test.go @@ -0,0 +1,52 @@ +package tests + +import ( + "context" + "testing" + "time" + + "github.com/Fantom-foundation/go-opera/tests/contracts/counter_event_emitter" + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/core/types" + "github.com/stretchr/testify/require" +) + +func TestLogSubscription_CanGetCallBacksForLogEvents(t *testing.T) { + const NumEvents = 3 + require := require.New(t) + net, err := StartIntegrationTestNet(t.TempDir()) + require.NoError(err, "Failed to start the fake network: ", err) + defer net.Stop() + + contract, _, err := DeployContract(net, counter_event_emitter.DeployCounterEventEmitter) + require.NoError(err) + + client, err := net.GetWebSocketClient() + require.NoError(err, "failed to get client; ", err) + defer client.Close() + + allLogs := make(chan types.Log, NumEvents) + subscription, err := client.SubscribeFilterLogs( + context.Background(), + ethereum.FilterQuery{}, + allLogs, + ) + require.NoError(err, "failed to subscribe to logs; ", err) + defer subscription.Unsubscribe() + + for range NumEvents { + _, err = net.Apply(contract.Increment) + require.NoError(err) + } + + for i := range NumEvents { + select { + case log := <-allLogs: + event, err := contract.ParseCount(log) + require.NoError(err) + require.Equal(uint64(i+1), event.TotalCount.Uint64()) + case <-time.After(5 * time.Second): + require.Fail("expected log event not received") + } + } +}