kubo/config/config_test.go
Marcin Rataj 71e883440e
Some checks are pending
CodeQL / codeql (push) Waiting to run
Docker Check / lint (push) Waiting to run
Docker Check / build (push) Waiting to run
Gateway Conformance / gateway-conformance (push) Waiting to run
Gateway Conformance / gateway-conformance-libp2p-experiment (push) Waiting to run
Go Build / go-build (push) Waiting to run
Go Check / go-check (push) Waiting to run
Go Lint / go-lint (push) Waiting to run
Go Test / go-test (push) Waiting to run
Interop / interop-prep (push) Waiting to run
Interop / helia-interop (push) Blocked by required conditions
Interop / ipfs-webui (push) Blocked by required conditions
Sharness / sharness-test (push) Waiting to run
Spell Check / spellcheck (push) Waiting to run
refactor(config): migration 17-to-18 to unify Provider/Reprovider into Provide.DHT (#10951)
* refactor: consolidate Provider/Reprovider into unified Provide config

- merge Provider and Reprovider configs into single Provide section
- add fs-repo-17-to-18 migration for config consolidation
- improve migration ergonomics with common package utilities
- convert deprecated "flat" strategy to "all" during migration
- improve Provide docs

* docs: add total_provide_count metric guidance

- document how to monitor provide success rates via prometheus metrics
- add performance comparison section to changelog
- explain how to evaluate sweep vs legacy provider effectiveness

* fix: add OpenTelemetry meter provider for metrics

- set up meter provider with Prometheus exporter in daemon
- enables metrics from external libs like go-libp2p-kad-dht
- fixes missing total_provide_count_total when SweepEnabled=true
- update docs to reflect actual metric names

---------

Co-authored-by: gammazero <11790789+gammazero@users.noreply.github.com>
Co-authored-by: guillaumemichel <guillaume@michel.id>
Co-authored-by: Daniel Norman <1992255+2color@users.noreply.github.com>
Co-authored-by: Hector Sanjuan <code@hector.link>
2025-09-18 22:17:43 +02:00

172 lines
4.4 KiB
Go

package config
import (
"testing"
)
func TestClone(t *testing.T) {
c := new(Config)
c.Identity.PeerID = "faketest"
c.API.HTTPHeaders = map[string][]string{"foo": {"bar"}}
newCfg, err := c.Clone()
if err != nil {
t.Fatal(err)
}
if newCfg.Identity.PeerID != c.Identity.PeerID {
t.Fatal("peer ID not preserved")
}
c.API.HTTPHeaders["foo"] = []string{"baz"}
if newCfg.API.HTTPHeaders["foo"][0] != "bar" {
t.Fatal("HTTP headers not preserved")
}
delete(c.API.HTTPHeaders, "foo")
if newCfg.API.HTTPHeaders["foo"][0] != "bar" {
t.Fatal("HTTP headers not preserved")
}
}
func TestReflectToMap(t *testing.T) {
// Helper function to create a test config with various field types
reflectedConfig := ReflectToMap(new(Config))
mapConfig, ok := reflectedConfig.(map[string]interface{})
if !ok {
t.Fatal("Config didn't convert to map")
}
reflectedIdentity, ok := mapConfig["Identity"]
if !ok {
t.Fatal("Identity field not found")
}
mapIdentity, ok := reflectedIdentity.(map[string]interface{})
if !ok {
t.Fatal("Identity field didn't convert to map")
}
// Test string field reflection
reflectedPeerID, ok := mapIdentity["PeerID"]
if !ok {
t.Fatal("PeerID field not found in Identity")
}
if _, ok := reflectedPeerID.(string); !ok {
t.Fatal("PeerID field didn't convert to string")
}
// Test omitempty json string field
reflectedPrivKey, ok := mapIdentity["PrivKey"]
if !ok {
t.Fatal("PrivKey omitempty field not found in Identity")
}
if _, ok := reflectedPrivKey.(string); !ok {
t.Fatal("PrivKey omitempty field didn't convert to string")
}
// Test slices field
reflectedBootstrap, ok := mapConfig["Bootstrap"]
if !ok {
t.Fatal("Bootstrap field not found in config")
}
bootstrap, ok := reflectedBootstrap.([]interface{})
if !ok {
t.Fatal("Bootstrap field didn't convert to []string")
}
if len(bootstrap) != 0 {
t.Fatal("Bootstrap len is incorrect")
}
reflectedDatastore, ok := mapConfig["Datastore"]
if !ok {
t.Fatal("Datastore field not found in config")
}
datastore, ok := reflectedDatastore.(map[string]interface{})
if !ok {
t.Fatal("Datastore field didn't convert to map")
}
storageGCWatermark, ok := datastore["StorageGCWatermark"]
if !ok {
t.Fatal("StorageGCWatermark field not found in Datastore")
}
// Test int field
if _, ok := storageGCWatermark.(int64); !ok {
t.Fatal("StorageGCWatermark field didn't convert to int64")
}
noSync, ok := datastore["NoSync"]
if !ok {
t.Fatal("NoSync field not found in Datastore")
}
// Test bool field
if _, ok := noSync.(bool); !ok {
t.Fatal("NoSync field didn't convert to bool")
}
reflectedDNS, ok := mapConfig["DNS"]
if !ok {
t.Fatal("DNS field not found in config")
}
DNS, ok := reflectedDNS.(map[string]interface{})
if !ok {
t.Fatal("DNS field didn't convert to map")
}
reflectedResolvers, ok := DNS["Resolvers"]
if !ok {
t.Fatal("Resolvers field not found in DNS")
}
// Test map field
if _, ok := reflectedResolvers.(map[string]interface{}); !ok {
t.Fatal("Resolvers field didn't convert to map")
}
// Test pointer field
if _, ok := DNS["MaxCacheTTL"].(map[string]interface{}); !ok {
// Since OptionalDuration only field is private, we cannot test it
t.Fatal("MaxCacheTTL field didn't convert to map")
}
}
// Test validation of options set through "ipfs config"
func TestCheckKey(t *testing.T) {
err := CheckKey("Foo.Bar")
if err == nil {
t.Fatal("Foo.Bar isn't a valid key in the config")
}
err = CheckKey("Provide.Strategy")
if err != nil {
t.Fatalf("%s: %s", err, "Provide.Strategy is a valid key in the config")
}
err = CheckKey("Provide.DHT.MaxWorkers")
if err != nil {
t.Fatalf("%s: %s", err, "Provide.DHT.MaxWorkers is a valid key in the config")
}
err = CheckKey("Provide.DHT.Interval")
if err != nil {
t.Fatalf("%s: %s", err, "Provide.DHT.Interval is a valid key in the config")
}
err = CheckKey("Provide.Foo")
if err == nil {
t.Fatal("Provide.Foo isn't a valid key in the config")
}
err = CheckKey("Gateway.PublicGateways.Foo.Paths")
if err != nil {
t.Fatalf("%s: %s", err, "Gateway.PublicGateways.Foo.Paths is a valid key in the config")
}
err = CheckKey("Gateway.PublicGateways.Foo.Bar")
if err == nil {
t.Fatal("Gateway.PublicGateways.Foo.Bar isn't a valid key in the config")
}
err = CheckKey("Plugins.Plugins.peerlog.Config.Enabled")
if err != nil {
t.Fatalf("%s: %s", err, "Plugins.Plugins.peerlog.Config.Enabled is a valid key in the config")
}
}