From 025343a64211a37b4202ecac40ef533deeced951 Mon Sep 17 00:00:00 2001 From: Sebastian Webber Date: Fri, 6 Feb 2026 02:03:48 -0300 Subject: [PATCH] fix: normalize environment_name to uppercase in api Fix case sensitivity bug where API returns zero memory values when environment_name parameter uses mixed case (e.g., "Mixed" instead of "MIXED"). Profile lookups in memory configuration maps require uppercase keys, but API was doing direct type cast without validation. This caused all memory parameters (shared_buffers, effective_cache_size, work_mem, maintenance_work_mem) to return 0 when map lookups failed. Add profile.Parse() function to centralize parsing logic and ensure case-insensitive matching through existing Set() normalization. Fixes #37 Signed-off-by: Sebastian Webber --- cmd/api/handlers/v1/config.go | 7 ++- cmd/api/handlers/v1/config_test.go | 69 ++++++++++++++++++++++++++++++ pkg/input/profile/profile.go | 11 +++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 cmd/api/handlers/v1/config_test.go diff --git a/cmd/api/handlers/v1/config.go b/cmd/api/handlers/v1/config.go index 7efe623..4d28dcf 100644 --- a/cmd/api/handlers/v1/config.go +++ b/cmd/api/handlers/v1/config.go @@ -172,6 +172,11 @@ func parseConfigArgs(c *fiber.Ctx) (*configArgs, error) { return nil, fmt.Errorf("could not parse total ram: %w", err) } + envName, err := profile.Parse(c.Query("environment_name", "WEB")) + if err != nil { + return nil, fmt.Errorf("could not parse environment name: %w", err) + } + // Set default log format based on PostgreSQL version defaultLogFormat := "stderr" if float32(pgVersion) >= 15.0 { @@ -182,7 +187,7 @@ func parseConfigArgs(c *fiber.Ctx) (*configArgs, error) { pgVersion: float32(pgVersion), totalRAM: parsedRAM, maxConn: maxConn, - envName: profile.Profile(c.Query("environment_name", "WEB")), + envName: envName, osType: c.Query("os_type", "linux"), arch: c.Query("arch", "amd64"), driveType: c.Query("drive_type", "HDD"), diff --git a/cmd/api/handlers/v1/config_test.go b/cmd/api/handlers/v1/config_test.go new file mode 100644 index 0000000..8e2921c --- /dev/null +++ b/cmd/api/handlers/v1/config_test.go @@ -0,0 +1,69 @@ +package v1 + +import ( + "net/http/httptest" + "testing" + + "github.com/gofiber/fiber/v2" + "github.com/pgconfig/api/pkg/input/profile" +) + +func TestParseConfigArgs_ProfileCaseInsensitive(t *testing.T) { + // Regression test for issue #37: environment_name should be case-insensitive + tests := []struct { + name string + environmentName string + expectedProfile profile.Profile + }{ + { + name: "uppercase MIXED", + environmentName: "MIXED", + expectedProfile: profile.Mixed, + }, + { + name: "mixed case Mixed", + environmentName: "Mixed", + expectedProfile: profile.Mixed, + }, + { + name: "lowercase mixed", + environmentName: "mixed", + expectedProfile: profile.Mixed, + }, + { + name: "mixed case WEB", + environmentName: "Web", + expectedProfile: profile.Web, + }, + { + name: "lowercase web", + environmentName: "web", + expectedProfile: profile.Web, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + app := fiber.New() + + app.Get("/test", func(c *fiber.Ctx) error { + args, err := parseConfigArgs(c) + if err != nil { + return err + } + + if args.envName != tt.expectedProfile { + t.Errorf("expected profile %v, got %v", tt.expectedProfile, args.envName) + } + + return c.SendStatus(200) + }) + + req := httptest.NewRequest("GET", "/test?environment_name="+tt.environmentName, nil) + _, err := app.Test(req) + if err != nil { + t.Fatalf("request failed: %v", err) + } + }) + } +} diff --git a/pkg/input/profile/profile.go b/pkg/input/profile/profile.go index 9d3b433..c97d2a0 100644 --- a/pkg/input/profile/profile.go +++ b/pkg/input/profile/profile.go @@ -53,3 +53,14 @@ func (e *Profile) Set(v string) error { func (e *Profile) Type() string { return "Profile" } + +// Parse parses a profile string and returns the normalized Profile. +// It normalizes the input to uppercase to ensure case-insensitive matching. +// Returns an error if the profile string is not valid. +func Parse(s string) (Profile, error) { + var p Profile + if err := p.Set(s); err != nil { + return "", err + } + return p, nil +}