diff --git a/go.mod b/go.mod index 8dad225..b87bd26 100644 --- a/go.mod +++ b/go.mod @@ -2,19 +2,4 @@ module notashelf.dev/ncro go 1.25.7 -require ( - github.com/dustin/go-humanize v1.0.1 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/ncruces/go-strftime v1.0.0 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect - github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect - golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 // indirect - golang.org/x/sys v0.37.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - modernc.org/libc v1.67.6 // indirect - modernc.org/mathutil v1.7.1 // indirect - modernc.org/memory v1.11.0 // indirect - modernc.org/sqlite v1.46.1 // indirect -) +require gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index f9c9829..a62c313 100644 --- a/go.sum +++ b/go.sum @@ -1,30 +1,4 @@ -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= -github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8= -github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok= -github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= -github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= -golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546 h1:mgKeJMpvi0yx/sU5GsxQ7p6s2wtOnGAHZWCHUM4KGzY= -golang.org/x/exp v0.0.0-20251023183803-a4bb9ffd2546/go.mod h1:j/pmGrbnkbPtQfxEe5D0VQhZC6qKbfKifgD0oM7sR70= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= -golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI= -modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE= -modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= -modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= -modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= -modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= -modernc.org/sqlite v1.46.1 h1:eFJ2ShBLIEnUWlLy12raN0Z1plqmFX9Qe3rjQTKt6sU= -modernc.org/sqlite v1.46.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA= diff --git a/internal/config/config.go b/internal/config/config.go index 6c98f5a..087dfa4 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -21,7 +21,7 @@ func (d *Duration) UnmarshalYAML(value *yaml.Node) error { // Try decoding as a raw int64 (nanoseconds) as fallback. var ns int64 if err2 := value.Decode(&ns); err2 != nil { - return fmt.Errorf("cannot unmarshal duration: %w", err) + return fmt.Errorf("cannot unmarshal duration (tried string: %v): %w", err, err2) } d.Duration = time.Duration(ns) return nil diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 7bf0a41..335f649 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -3,6 +3,7 @@ package config_test import ( "os" "testing" + "time" "notashelf.dev/ncro/internal/config" ) @@ -61,3 +62,53 @@ func TestEnvOverride(t *testing.T) { t.Errorf("env override listen = %q, want :1234", cfg.Server.Listen) } } + +func TestDurationParsing(t *testing.T) { + yamlContent := ` +server: + listen: ":8080" + read_timeout: 30s + write_timeout: 1m +cache: + ttl: 2h +mesh: + gossip_interval: 45s +` + f, _ := os.CreateTemp("", "ncro-dur-*.yaml") + defer os.Remove(f.Name()) + f.WriteString(yamlContent) + f.Close() + + cfg, err := config.Load(f.Name()) + if err != nil { + t.Fatalf("Load error: %v", err) + } + if cfg.Server.ReadTimeout.Duration != 30*time.Second { + t.Errorf("read_timeout = %v, want 30s", cfg.Server.ReadTimeout.Duration) + } + if cfg.Server.WriteTimeout.Duration != time.Minute { + t.Errorf("write_timeout = %v, want 1m", cfg.Server.WriteTimeout.Duration) + } + if cfg.Cache.TTL.Duration != 2*time.Hour { + t.Errorf("ttl = %v, want 2h", cfg.Cache.TTL.Duration) + } + if cfg.Mesh.GossipInterval.Duration != 45*time.Second { + t.Errorf("gossip_interval = %v, want 45s", cfg.Mesh.GossipInterval.Duration) + } +} + +func TestInvalidDuration(t *testing.T) { + yamlContent := ` +server: + read_timeout: "bananas" +` + f, _ := os.CreateTemp("", "ncro-bad-*.yaml") + defer os.Remove(f.Name()) + f.WriteString(yamlContent) + f.Close() + + _, err := config.Load(f.Name()) + if err == nil { + t.Error("expected error for invalid duration string, got nil") + } +}