kubo/plugin/plugins/telemetry/telemetry_test.go
Marcin Rataj 6a008fc74c
refactor: apply go fix modernizers from Go 1.26 (#11190)
* chore: apply go fix modernizers from Go 1.26

automated refactoring: interface{} to any, slices.Contains,
and other idiomatic updates.

* feat(ci): add `go fix` check to Go analysis workflow

ensures Go 1.26 modernizers are applied, fails CI if `go fix ./...`
produces any changes (similar to existing `go fmt` enforcement)
2026-02-11 01:01:32 +01:00

171 lines
3.5 KiB
Go

package telemetry
import (
"context"
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"os"
"testing"
"github.com/cockroachdb/pebble/v2"
logging "github.com/ipfs/go-log/v2"
"github.com/ipfs/kubo/config"
"github.com/ipfs/kubo/core"
"github.com/ipfs/kubo/core/node/libp2p"
"github.com/ipfs/kubo/plugin"
"github.com/ipfs/kubo/plugin/plugins/pebbleds"
"github.com/ipfs/kubo/repo/fsrepo"
)
func mockServer(t *testing.T) (*httptest.Server, func() LogEvent) {
t.Helper()
var e LogEvent
// Create a mock HTTP test server
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Check if the request is POST to the correct endpoint
if r.Method != "POST" || r.URL.Path != "/" {
t.Log("invalid request")
http.Error(w, "invalid request", http.StatusBadRequest)
return
}
// Check content type
if r.Header.Get("Content-Type") != "application/json" {
t.Log("invalid content type")
http.Error(w, "invalid content type", http.StatusBadRequest)
return
}
// Check if the body is not empty
if r.Body == nil {
t.Log("empty body")
http.Error(w, "empty body", http.StatusBadRequest)
return
}
// Read the body
body, _ := io.ReadAll(r.Body)
if len(body) == 0 {
t.Log("zero-length body")
http.Error(w, "empty body", http.StatusBadRequest)
return
}
t.Logf("Received telemetry:\n %s", string(body))
err := json.Unmarshal(body, &e)
if err != nil {
t.Log("error unmarshaling event", err)
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
// Return success
w.WriteHeader(http.StatusOK)
})), func() LogEvent { return e }
}
func makeNode(t *testing.T) (node *core.IpfsNode, repopath string) {
t.Helper()
// Create a Temporary Repo
repoPath, err := os.MkdirTemp("", "ipfs-shell")
if err != nil {
t.Fatal(err)
}
pebbledspli := pebbleds.Plugins[0]
pebbledspl, ok := pebbledspli.(plugin.PluginDatastore)
if !ok {
t.Fatal("bad datastore plugin")
}
err = fsrepo.AddDatastoreConfigHandler(pebbledspl.DatastoreTypeName(), pebbledspl.DatastoreConfigParser())
if err != nil {
t.Fatal(err)
}
// Create a config with default options and a 2048 bit key
cfg, err := config.Init(io.Discard, 2048)
if err != nil {
t.Fatal(err)
}
cfg.Datastore.Spec = map[string]any{
"type": "pebbleds",
"prefix": "pebble.datastore",
"path": "pebbleds",
"formatMajorVersion": int(pebble.FormatNewest),
}
// Create the repo with the config
err = fsrepo.Init(repoPath, cfg)
if err != nil {
t.Fatal(err)
}
// Open the repo
repo, err := fsrepo.Open(repoPath)
if err != nil {
t.Fatal(err)
}
// Construct the node
nodeOptions := &core.BuildCfg{
Online: true,
Routing: libp2p.NilRouterOption,
Repo: repo,
}
node, err = core.NewNode(context.Background(), nodeOptions)
if err != nil {
t.Fatal(err)
}
node.IsDaemon = true
return
}
func TestSendTelemetry(t *testing.T) {
if err := logging.SetLogLevel("telemetry", "DEBUG"); err != nil {
t.Fatal(err)
}
ts, eventGetter := mockServer(t)
defer ts.Close()
node, repoPath := makeNode(t)
// Create a plugin instance
p := &telemetryPlugin{
runOnce: true,
}
// Initialize the plugin
pe := &plugin.Environment{
Repo: repoPath,
Config: nil,
}
err := p.Init(pe)
if err != nil {
t.Fatalf("Init() failed: %v", err)
}
p.endpoint = ts.URL
// Start the plugin
err = p.Start(node)
if err != nil {
t.Fatalf("Start() failed: %v", err)
}
e := eventGetter()
if e.UUID != p.event.UUID {
t.Fatal("uuid mismatch")
}
}