Files
akvorado/inlet/kafka/functional_test.go
2025-10-26 12:14:20 +01:00

126 lines
3.2 KiB
Go

// SPDX-FileCopyrightText: 2022 Free Mobile
// SPDX-License-Identifier: AGPL-3.0-only
package kafka
import (
"context"
"fmt"
"math/rand/v2"
"sync"
"testing"
"time"
"github.com/twmb/franz-go/pkg/kfake"
"github.com/twmb/franz-go/pkg/kgo"
"akvorado/common/daemon"
"akvorado/common/helpers"
"akvorado/common/kafka"
"akvorado/common/pb"
"akvorado/common/reporter"
)
func TestFakeKafka(t *testing.T) {
r := reporter.NewMock(t)
topicName := fmt.Sprintf("test-topic-%d", rand.Int())
expectedTopicName := fmt.Sprintf("%s-v%d", topicName, pb.Version)
cluster, err := kfake.NewCluster(
kfake.NumBrokers(1),
kfake.SeedTopics(1, expectedTopicName),
kfake.WithLogger(kafka.NewLogger(r)),
)
if err != nil {
t.Fatalf("NewCluster() error: %v", err)
}
defer cluster.Close()
configuration := DefaultConfiguration()
configuration.Topic = topicName
configuration.Brokers = cluster.ListenAddrs()
c, err := New(r, configuration, Dependencies{Daemon: daemon.NewMock(t)})
if err != nil {
t.Fatalf("New() error:\n%+v", err)
}
helpers.StartStop(t, c)
const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
msg1 := make([]byte, 50)
msg2 := make([]byte, 50)
for i := range msg1 {
msg1[i] = letters[rand.IntN(len(letters))]
}
for i := range msg2 {
msg2[i] = letters[rand.IntN(len(letters))]
}
var wg sync.WaitGroup
wg.Add(2)
c.Send("127.0.0.1", msg1, func() { wg.Done() })
c.Send("127.0.0.1", msg2, func() { wg.Done() })
c.Flush(t)
done := make(chan struct{})
go func() {
wg.Wait()
close(done)
}()
select {
case <-done:
case <-time.After(time.Second):
t.Fatal("Send() timeout")
}
gotMetrics := r.GetMetrics("akvorado_inlet_kafka_", "sent_", "connects_")
expectedMetrics := map[string]string{
// Our own metrics
`sent_bytes_total{exporter="127.0.0.1"}`: "100",
`sent_messages_total{exporter="127.0.0.1"}`: "2",
// From franz-go
`connects_total{node_id="0"}`: "2",
`connects_total{node_id="seed_0"}`: "1",
}
if diff := helpers.Diff(gotMetrics, expectedMetrics); diff != "" {
t.Fatalf("Metrics (-got, +want):\n%s", diff)
}
// Try to consume the two messages using franz-go
consumer, err := kgo.NewClient(
kgo.SeedBrokers(cluster.ListenAddrs()...),
kgo.ConsumeTopics(expectedTopicName),
kgo.ConsumeResetOffset(kgo.NewOffset().AtStart()),
kgo.FetchMaxWait(10*time.Millisecond),
)
if err != nil {
t.Fatalf("NewClient() error:\n%+v", err)
}
defer consumer.Close()
got := []string{}
expected := []string{string(msg1), string(msg2)}
timeout := time.After(15 * time.Second)
for len(got) < len(expected) {
select {
case <-timeout:
t.Fatalf("Timeout waiting for messages. Got %d of %d messages", len(got), len(expected))
default:
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
fetches := consumer.PollFetches(ctx)
cancel()
if errs := fetches.Errors(); len(errs) > 0 {
t.Logf("PollFetches() error: %+v", err)
time.Sleep(100 * time.Millisecond)
continue
}
fetches.EachPartition(func(p kgo.FetchTopicPartition) {
for _, record := range p.Records {
got = append(got, string(record.Value))
}
})
}
}
if diff := helpers.Diff(got, expected); diff != "" {
t.Fatalf("Didn't received the expected messages (-got, +want):\n%s", diff)
}
}