master
go 170 lines 3.51 KB
Raw
1 package telemetry
2
3 import (
4 "context"
5 "encoding/json"
6 "io"
7 "net/http"
8 "net/http/httptest"
9 "os"
10 "testing"
11
12 "github.com/cockroachdb/pebble/v2"
13 logging "github.com/ipfs/go-log/v2"
14 "github.com/ipfs/kubo/config"
15 "github.com/ipfs/kubo/core"
16 "github.com/ipfs/kubo/core/node/libp2p"
17 "github.com/ipfs/kubo/plugin"
18 "github.com/ipfs/kubo/plugin/plugins/pebbleds"
19 "github.com/ipfs/kubo/repo/fsrepo"
20 )
21
22 func mockServer(t *testing.T) (*httptest.Server, func() LogEvent) {
23 t.Helper()
24
25 var e LogEvent
26
27 // Create a mock HTTP test server
28 return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
29 // Check if the request is POST to the correct endpoint
30 if r.Method != "POST" || r.URL.Path != "/" {
31 t.Log("invalid request")
32 http.Error(w, "invalid request", http.StatusBadRequest)
33 return
34 }
35
36 // Check content type
37 if r.Header.Get("Content-Type") != "application/json" {
38 t.Log("invalid content type")
39 http.Error(w, "invalid content type", http.StatusBadRequest)
40 return
41 }
42
43 // Check if the body is not empty
44 if r.Body == nil {
45 t.Log("empty body")
46 http.Error(w, "empty body", http.StatusBadRequest)
47 return
48 }
49
50 // Read the body
51 body, _ := io.ReadAll(r.Body)
52 if len(body) == 0 {
53 t.Log("zero-length body")
54 http.Error(w, "empty body", http.StatusBadRequest)
55 return
56 }
57
58 t.Logf("Received telemetry:\n %s", string(body))
59
60 err := json.Unmarshal(body, &e)
61 if err != nil {
62 t.Log("error unmarshaling event", err)
63 http.Error(w, err.Error(), http.StatusBadRequest)
64 return
65 }
66
67 // Return success
68 w.WriteHeader(http.StatusOK)
69 })), func() LogEvent { return e }
70 }
71
72 func makeNode(t *testing.T) (node *core.IpfsNode, repopath string) {
73 t.Helper()
74
75 // Create a Temporary Repo
76 repoPath, err := os.MkdirTemp("", "ipfs-shell")
77 if err != nil {
78 t.Fatal(err)
79 }
80
81 pebbledspli := pebbleds.Plugins[0]
82 pebbledspl, ok := pebbledspli.(plugin.PluginDatastore)
83 if !ok {
84 t.Fatal("bad datastore plugin")
85 }
86
87 err = fsrepo.AddDatastoreConfigHandler(pebbledspl.DatastoreTypeName(), pebbledspl.DatastoreConfigParser())
88 if err != nil {
89 t.Fatal(err)
90 }
91
92 // Create a config with default options and a 2048 bit key
93 cfg, err := config.Init(io.Discard, 2048)
94 if err != nil {
95 t.Fatal(err)
96 }
97
98 cfg.Datastore.Spec = map[string]any{
99 "type": "pebbleds",
100 "prefix": "pebble.datastore",
101 "path": "pebbleds",
102 "formatMajorVersion": int(pebble.FormatNewest),
103 }
104
105 // Create the repo with the config
106 err = fsrepo.Init(repoPath, cfg)
107 if err != nil {
108 t.Fatal(err)
109 }
110
111 // Open the repo
112 repo, err := fsrepo.Open(repoPath)
113 if err != nil {
114 t.Fatal(err)
115 }
116
117 // Construct the node
118
119 nodeOptions := &core.BuildCfg{
120 Online: true,
121 Routing: libp2p.NilRouterOption,
122 Repo: repo,
123 }
124
125 node, err = core.NewNode(context.Background(), nodeOptions)
126 if err != nil {
127 t.Fatal(err)
128 }
129
130 node.IsDaemon = true
131 return
132 }
133
134 func TestSendTelemetry(t *testing.T) {
135 if err := logging.SetLogLevel("telemetry", "DEBUG"); err != nil {
136 t.Fatal(err)
137 }
138 ts, eventGetter := mockServer(t)
139 defer ts.Close()
140
141 node, repoPath := makeNode(t)
142
143 // Create a plugin instance
144 p := &telemetryPlugin{
145 runOnce: true,
146 }
147
148 // Initialize the plugin
149 pe := &plugin.Environment{
150 Repo: repoPath,
151 Config: nil,
152 }
153 err := p.Init(pe)
154 if err != nil {
155 t.Fatalf("Init() failed: %v", err)
156 }
157
158 p.endpoint = ts.URL
159
160 // Start the plugin
161 err = p.Start(node)
162 if err != nil {
163 t.Fatalf("Start() failed: %v", err)
164 }
165
166 e := eventGetter()
167 if e.UUID != p.event.UUID {
168 t.Fatal("uuid mismatch")
169 }
170 }