|
@@ -0,0 +1,288 @@
|
|
|
+package godotenv
|
|
|
+
|
|
|
+import (
|
|
|
+ "os"
|
|
|
+ "testing"
|
|
|
+)
|
|
|
+
|
|
|
+var noopPresets = make(map[string]string)
|
|
|
+
|
|
|
+func parseAndCompare(t *testing.T, rawEnvLine string, expectedKey string, expectedValue string) {
|
|
|
+ key, value, _ := parseLine(rawEnvLine)
|
|
|
+ if key != expectedKey || value != expectedValue {
|
|
|
+ t.Errorf("Expected '%v' to parse as '%v' => '%v', got '%v' => '%v' instead", rawEnvLine, expectedKey, expectedValue, key, value)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func loadEnvAndCompareValues(t *testing.T, loader func(files ...string) error, envFileName string, expectedValues map[string]string, presets map[string]string) {
|
|
|
+
|
|
|
+ os.Clearenv()
|
|
|
+
|
|
|
+ for k, v := range presets {
|
|
|
+ os.Setenv(k, v)
|
|
|
+ }
|
|
|
+
|
|
|
+ err := loader(envFileName)
|
|
|
+ if err != nil {
|
|
|
+ t.Fatalf("Error loading %v", envFileName)
|
|
|
+ }
|
|
|
+
|
|
|
+ for k := range expectedValues {
|
|
|
+ envValue := os.Getenv(k)
|
|
|
+ v := expectedValues[k]
|
|
|
+ if envValue != v {
|
|
|
+ t.Errorf("Mismatch for key '%v': expected '%v' got '%v'", k, v, envValue)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestLoadWithNoArgsLoadsDotEnv(t *testing.T) {
|
|
|
+ err := Load()
|
|
|
+ pathError := err.(*os.PathError)
|
|
|
+ if pathError == nil || pathError.Op != "open" || pathError.Path != ".env" {
|
|
|
+ t.Errorf("Didn't try and open .env by default")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestOverloadWithNoArgsOverloadsDotEnv(t *testing.T) {
|
|
|
+ err := Overload()
|
|
|
+ pathError := err.(*os.PathError)
|
|
|
+ if pathError == nil || pathError.Op != "open" || pathError.Path != ".env" {
|
|
|
+ t.Errorf("Didn't try and open .env by default")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestLoadFileNotFound(t *testing.T) {
|
|
|
+ err := Load("somefilethatwillneverexistever.env")
|
|
|
+ if err == nil {
|
|
|
+ t.Error("File wasn't found but Load didn't return an error")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestOverloadFileNotFound(t *testing.T) {
|
|
|
+ err := Overload("somefilethatwillneverexistever.env")
|
|
|
+ if err == nil {
|
|
|
+ t.Error("File wasn't found but Overload didn't return an error")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestReadPlainEnv(t *testing.T) {
|
|
|
+ envFileName := "fixtures/plain.env"
|
|
|
+ expectedValues := map[string]string{
|
|
|
+ "OPTION_A": "1",
|
|
|
+ "OPTION_B": "2",
|
|
|
+ "OPTION_C": "3",
|
|
|
+ "OPTION_D": "4",
|
|
|
+ "OPTION_E": "5",
|
|
|
+ }
|
|
|
+
|
|
|
+ envMap, err := Read(envFileName)
|
|
|
+ if err != nil {
|
|
|
+ t.Error("Error reading file")
|
|
|
+ }
|
|
|
+
|
|
|
+ if len(envMap) != len(expectedValues) {
|
|
|
+ t.Error("Didn't get the right size map back")
|
|
|
+ }
|
|
|
+
|
|
|
+ for key, value := range expectedValues {
|
|
|
+ if envMap[key] != value {
|
|
|
+ t.Error("Read got one of the keys wrong")
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestLoadDoesNotOverride(t *testing.T) {
|
|
|
+ envFileName := "fixtures/plain.env"
|
|
|
+
|
|
|
+
|
|
|
+ presets := map[string]string{
|
|
|
+ "OPTION_A": "do_not_override",
|
|
|
+ }
|
|
|
+
|
|
|
+ expectedValues := map[string]string{
|
|
|
+ "OPTION_A": "do_not_override",
|
|
|
+ }
|
|
|
+ loadEnvAndCompareValues(t, Load, envFileName, expectedValues, presets)
|
|
|
+}
|
|
|
+
|
|
|
+func TestOveroadDoesOverride(t *testing.T) {
|
|
|
+ envFileName := "fixtures/plain.env"
|
|
|
+
|
|
|
+
|
|
|
+ presets := map[string]string{
|
|
|
+ "OPTION_A": "do_not_override",
|
|
|
+ }
|
|
|
+
|
|
|
+ expectedValues := map[string]string{
|
|
|
+ "OPTION_A": "1",
|
|
|
+ }
|
|
|
+ loadEnvAndCompareValues(t, Overload, envFileName, expectedValues, presets)
|
|
|
+}
|
|
|
+
|
|
|
+func TestLoadPlainEnv(t *testing.T) {
|
|
|
+ envFileName := "fixtures/plain.env"
|
|
|
+ expectedValues := map[string]string{
|
|
|
+ "OPTION_A": "1",
|
|
|
+ "OPTION_B": "2",
|
|
|
+ "OPTION_C": "3",
|
|
|
+ "OPTION_D": "4",
|
|
|
+ "OPTION_E": "5",
|
|
|
+ }
|
|
|
+
|
|
|
+ loadEnvAndCompareValues(t, Load, envFileName, expectedValues, noopPresets)
|
|
|
+}
|
|
|
+
|
|
|
+func TestLoadExportedEnv(t *testing.T) {
|
|
|
+ envFileName := "fixtures/exported.env"
|
|
|
+ expectedValues := map[string]string{
|
|
|
+ "OPTION_A": "2",
|
|
|
+ "OPTION_B": "\n",
|
|
|
+ }
|
|
|
+
|
|
|
+ loadEnvAndCompareValues(t, Load, envFileName, expectedValues, noopPresets)
|
|
|
+}
|
|
|
+
|
|
|
+func TestLoadEqualsEnv(t *testing.T) {
|
|
|
+ envFileName := "fixtures/equals.env"
|
|
|
+ expectedValues := map[string]string{
|
|
|
+ "OPTION_A": "postgres://localhost:5432/database?sslmode=disable",
|
|
|
+ }
|
|
|
+
|
|
|
+ loadEnvAndCompareValues(t, Load, envFileName, expectedValues, noopPresets)
|
|
|
+}
|
|
|
+
|
|
|
+func TestLoadQuotedEnv(t *testing.T) {
|
|
|
+ envFileName := "fixtures/quoted.env"
|
|
|
+ expectedValues := map[string]string{
|
|
|
+ "OPTION_A": "1",
|
|
|
+ "OPTION_B": "2",
|
|
|
+ "OPTION_C": "",
|
|
|
+ "OPTION_D": "\n",
|
|
|
+ "OPTION_E": "1",
|
|
|
+ "OPTION_F": "2",
|
|
|
+ "OPTION_G": "",
|
|
|
+ "OPTION_H": "\n",
|
|
|
+ }
|
|
|
+
|
|
|
+ loadEnvAndCompareValues(t, Load, envFileName, expectedValues, noopPresets)
|
|
|
+}
|
|
|
+
|
|
|
+func TestActualEnvVarsAreLeftAlone(t *testing.T) {
|
|
|
+ os.Clearenv()
|
|
|
+ os.Setenv("OPTION_A", "actualenv")
|
|
|
+ _ = Load("fixtures/plain.env")
|
|
|
+
|
|
|
+ if os.Getenv("OPTION_A") != "actualenv" {
|
|
|
+ t.Error("An ENV var set earlier was overwritten")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestParsing(t *testing.T) {
|
|
|
+
|
|
|
+ parseAndCompare(t, "FOO=bar", "FOO", "bar")
|
|
|
+
|
|
|
+
|
|
|
+ parseAndCompare(t, "FOO =bar", "FOO", "bar")
|
|
|
+ parseAndCompare(t, "FOO= bar", "FOO", "bar")
|
|
|
+
|
|
|
+
|
|
|
+ parseAndCompare(t, "FOO=\"bar\"", "FOO", "bar")
|
|
|
+
|
|
|
+
|
|
|
+ parseAndCompare(t, "FOO='bar'", "FOO", "bar")
|
|
|
+
|
|
|
+
|
|
|
+ parseAndCompare(t, "FOO=escaped\\\"bar\"", "FOO", "escaped\"bar")
|
|
|
+
|
|
|
+
|
|
|
+ parseAndCompare(t, "OPTION_A: 1", "OPTION_A", "1")
|
|
|
+
|
|
|
+
|
|
|
+ parseAndCompare(t, "export OPTION_A=2", "OPTION_A", "2")
|
|
|
+ parseAndCompare(t, "export OPTION_B='\\n'", "OPTION_B", "\n")
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ parseAndCompare(t, "FOO=\"bar\\nbaz\"", "FOO", "bar\nbaz")
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ parseAndCompare(t, "FOO.BAR=foobar", "FOO.BAR", "foobar")
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ parseAndCompare(t, "FOO=foobar=", "FOO", "foobar=")
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ parseAndCompare(t, "FOO=bar ", "FOO", "bar")
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ parseAndCompare(t, "FOO=bar # this is foo", "FOO", "bar")
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ parseAndCompare(t, "FOO=\"bar#baz\" # comment", "FOO", "bar#baz")
|
|
|
+ parseAndCompare(t, "FOO='bar#baz' # comment", "FOO", "bar#baz")
|
|
|
+ parseAndCompare(t, "FOO=\"bar#baz#bang\" # comment", "FOO", "bar#baz#bang")
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ parseAndCompare(t, "FOO=\"ba#r\"", "FOO", "ba#r")
|
|
|
+ parseAndCompare(t, "FOO='ba#r'", "FOO", "ba#r")
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ badlyFormattedLine := "lol$wut"
|
|
|
+ _, _, err := parseLine(badlyFormattedLine)
|
|
|
+ if err == nil {
|
|
|
+ t.Errorf("Expected \"%v\" to return error, but it didn't", badlyFormattedLine)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestLinesToIgnore(t *testing.T) {
|
|
|
+
|
|
|
+
|
|
|
+ if !isIgnoredLine("\n") {
|
|
|
+ t.Error("Line with nothing but line break wasn't ignored")
|
|
|
+ }
|
|
|
+
|
|
|
+ if !isIgnoredLine("\t\t ") {
|
|
|
+ t.Error("Line full of whitespace wasn't ignored")
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if !isIgnoredLine("# comment") {
|
|
|
+ t.Error("Comment wasn't ignored")
|
|
|
+ }
|
|
|
+
|
|
|
+ if !isIgnoredLine("\t#comment") {
|
|
|
+ t.Error("Indented comment wasn't ignored")
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if isIgnoredLine("export OPTION_B='\\n'") {
|
|
|
+ t.Error("ignoring a perfectly valid line to parse")
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestErrorReadDirectory(t *testing.T) {
|
|
|
+ envFileName := "fixtures/"
|
|
|
+ envMap, err := Read(envFileName)
|
|
|
+
|
|
|
+ if err == nil {
|
|
|
+ t.Errorf("Expected error, got %v", envMap)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func TestErrorParsing(t *testing.T) {
|
|
|
+ envFileName := "fixtures/invalid1.env"
|
|
|
+ envMap, err := Read(envFileName)
|
|
|
+ if err == nil {
|
|
|
+ t.Errorf("Expected error, got %v", envMap)
|
|
|
+ }
|
|
|
+}
|