package env import ( "fmt" "os" "path/filepath" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestGetEnv_ValidFile(t *testing.T) { // Create a temporary file with valid env content content := `KEY1=value1 KEY2=value2 KEY3=value with spaces KEY4=value,with,commas EMPTY_VALUE= ` tmpFile := createTempFile(t, content) defer os.Remove(tmpFile) env, err := GetEnv(tmpFile) require.NoError(t, err) assert.Equal(t, "value1", env["KEY1"]) assert.Equal(t, "value2", env["KEY2"]) assert.Equal(t, "value with spaces", env["KEY3"]) assert.Equal(t, "value,with,commas", env["KEY4"]) assert.Equal(t, "", env["EMPTY_VALUE"]) assert.Len(t, env, 5) } func TestGetEnv_WithWhitespace(t *testing.T) { content := ` KEY1 = value1 KEY2 = value2 KEY3= value3 KEY4 =value4 ` tmpFile := createTempFile(t, content) defer os.Remove(tmpFile) env, err := GetEnv(tmpFile) require.NoError(t, err) assert.Equal(t, "value1", env["KEY1"]) assert.Equal(t, "value2", env["KEY2"]) assert.Equal(t, "value3", env["KEY3"]) assert.Equal(t, "value4", env["KEY4"]) } func TestGetEnv_WithEmptyLines(t *testing.T) { content := `KEY1=value1 KEY2=value2 KEY3=value3 ` tmpFile := createTempFile(t, content) defer os.Remove(tmpFile) env, err := GetEnv(tmpFile) require.NoError(t, err) assert.Equal(t, "value1", env["KEY1"]) assert.Equal(t, "value2", env["KEY2"]) assert.Equal(t, "value3", env["KEY3"]) assert.Len(t, env, 3) } func TestGetEnv_WithEqualsInValue(t *testing.T) { content := `KEY1=value=with=equals KEY2=http://example.com?param=value ` tmpFile := createTempFile(t, content) defer os.Remove(tmpFile) env, err := GetEnv(tmpFile) require.NoError(t, err) assert.Equal(t, "value=with=equals", env["KEY1"]) assert.Equal(t, "http://example.com?param=value", env["KEY2"]) } func TestGetEnv_LineWithoutEquals(t *testing.T) { // Lines without equals signs should be skipped gracefully content := `KEY1=value1 INVALID_LINE_WITHOUT_EQUALS KEY2=value2 ` tmpFile := createTempFile(t, content) defer os.Remove(tmpFile) env, err := GetEnv(tmpFile) require.NoError(t, err) // Should only contain the valid key-value pairs assert.Equal(t, "value1", env["KEY1"]) assert.Equal(t, "value2", env["KEY2"]) assert.Len(t, env, 2) } func TestGetEnv_FileNotFound(t *testing.T) { env, err := GetEnv("nonexistent_file.env") assert.Error(t, err) assert.Nil(t, env) } func TestGetEnv_EmptyFile(t *testing.T) { tmpFile := createTempFile(t, "") defer os.Remove(tmpFile) env, err := GetEnv(tmpFile) require.NoError(t, err) assert.Empty(t, env) } func TestGetEnv_OnlyWhitespaceLines(t *testing.T) { content := ` ` tmpFile := createTempFile(t, content) defer os.Remove(tmpFile) env, err := GetEnv(tmpFile) require.NoError(t, err) assert.Empty(t, env) } func TestLookupEnv_ExistingKey(t *testing.T) { env := Env{ "KEY1": "value1", "KEY2": "value2", } value, ok := env.LookupEnv("KEY1") assert.True(t, ok) assert.Equal(t, "value1", value) value, ok = env.LookupEnv("KEY2") assert.True(t, ok) assert.Equal(t, "value2", value) } func TestLookupEnv_NonExistingKey(t *testing.T) { env := Env{ "KEY1": "value1", } value, ok := env.LookupEnv("NONEXISTENT") assert.False(t, ok) assert.Equal(t, "", value) } func TestLookupEnv_EmptyEnv(t *testing.T) { env := Env{} value, ok := env.LookupEnv("ANY_KEY") assert.False(t, ok) assert.Equal(t, "", value) } func TestLookupEnv_EmptyValue(t *testing.T) { env := Env{ "EMPTY_KEY": "", } value, ok := env.LookupEnv("EMPTY_KEY") assert.True(t, ok) assert.Equal(t, "", value) } func TestGetEnv_SpecialCharacters(t *testing.T) { content := `KEY_WITH_UNDERSCORE=value_with_underscore KEY-WITH-DASH=value-with-dash KEY.WITH.DOT=value.with.dot KEY123=value123 UNICODE_KEY=value_with_üñíçødé SYMBOLS=!@#$%^&*() QUOTES="quoted value" SINGLE_QUOTES='single quoted' ` tmpFile := createTempFile(t, content) defer os.Remove(tmpFile) env, err := GetEnv(tmpFile) require.NoError(t, err) assert.Equal(t, "value_with_underscore", env["KEY_WITH_UNDERSCORE"]) assert.Equal(t, "value-with-dash", env["KEY-WITH-DASH"]) assert.Equal(t, "value.with.dot", env["KEY.WITH.DOT"]) assert.Equal(t, "value123", env["KEY123"]) assert.Equal(t, "value_with_üñíçødé", env["UNICODE_KEY"]) assert.Equal(t, "!@#$%^&*()", env["SYMBOLS"]) assert.Equal(t, "\"quoted value\"", env["QUOTES"]) assert.Equal(t, "'single quoted'", env["SINGLE_QUOTES"]) } func TestGetEnv_LongValues(t *testing.T) { longValue := strings.Repeat("a", 1000) content := fmt.Sprintf("LONG_KEY=%s\nSHORT_KEY=short", longValue) tmpFile := createTempFile(t, content) defer os.Remove(tmpFile) env, err := GetEnv(tmpFile) require.NoError(t, err) assert.Equal(t, longValue, env["LONG_KEY"]) assert.Equal(t, "short", env["SHORT_KEY"]) assert.Len(t, env, 2) } func TestGetEnv_MixedValidInvalid(t *testing.T) { content := `VALID1=value1 INVALID_LINE_NO_EQUALS VALID2=value2 ANOTHER_INVALID VALID3=value3 =EMPTY_KEY_NAME KEY_WITH_EMPTY_VALUE= ` tmpFile := createTempFile(t, content) defer os.Remove(tmpFile) env, err := GetEnv(tmpFile) require.NoError(t, err) // Should only contain valid entries assert.Equal(t, "value1", env["VALID1"]) assert.Equal(t, "value2", env["VALID2"]) assert.Equal(t, "value3", env["VALID3"]) assert.Equal(t, "", env["KEY_WITH_EMPTY_VALUE"]) assert.Equal(t, "EMPTY_KEY_NAME", env[""]) // Empty key name with value assert.Len(t, env, 5) } // Helper function to create temporary files for testing func createTempFile(t *testing.T, content string) string { tmpDir := t.TempDir() tmpFile := filepath.Join(tmpDir, "test.env") err := os.WriteFile(tmpFile, []byte(content), 0644) require.NoError(t, err) return tmpFile }