main
  1package procfile
  2
  3import (
  4	"os"
  5	"strings"
  6	"testing"
  7)
  8
  9func TestParse(t *testing.T) {
 10	t.Run("TestParseBasic", func(t *testing.T) {
 11		input := "web: echo 'Hello World'\n"
 12		procs := Parse(strings.NewReader(input))
 13
 14		if len(procs) != 1 {
 15			t.Errorf("Expected 1 process, got %d", len(procs))
 16		}
 17
 18		proc := procs[0]
 19		if proc.name != "web" {
 20			t.Errorf("Expected name 'web', got '%s'", proc.name)
 21		}
 22
 23		expectedArgs := []string{"echo", "'Hello", "World'"}
 24		args := proc.args
 25		if len(args) != len(expectedArgs) {
 26			t.Errorf("Expected %d args, got %d", len(expectedArgs), len(args))
 27		}
 28
 29		for i, expected := range expectedArgs {
 30			if args[i] != expected {
 31				t.Errorf("Expected arg[%d] '%s', got '%s'", i, expected, args[i])
 32			}
 33		}
 34	})
 35
 36	t.Run("TestParseMultiple", func(t *testing.T) {
 37		input := `web: ./server -port 8080
 38worker: ./worker -queue tasks
 39redis: redis-server --port 6379`
 40
 41		procs := Parse(strings.NewReader(input))
 42
 43		if len(procs) != 3 {
 44			t.Errorf("Expected 3 processes, got %d", len(procs))
 45		}
 46
 47		expectedNames := []string{"web", "worker", "redis"}
 48		for i, expectedName := range expectedNames {
 49			if procs[i].name != expectedName {
 50				t.Errorf("Expected process[%d] name '%s', got '%s'", i, expectedName, procs[i].name)
 51			}
 52		}
 53	})
 54
 55	t.Run("TestParseCommentsAndEmptyLines", func(t *testing.T) {
 56		input := `# This is a comment
 57web: echo 'Web server'
 58
 59# Another comment
 60worker: echo 'Background worker'
 61
 62# Empty lines should be ignored`
 63
 64		procs := Parse(strings.NewReader(input))
 65
 66		if len(procs) != 2 {
 67			t.Errorf("Expected 2 processes, got %d", len(procs))
 68		}
 69
 70		if procs[0].name != "web" || procs[1].name != "worker" {
 71			t.Errorf("Expected processes 'web' and 'worker', got '%s' and '%s'",
 72				procs[0].name, procs[1].name)
 73		}
 74	})
 75
 76	t.Run("TestParseInvalidLines", func(t *testing.T) {
 77		input := `web echo 'missing colon'
 78worker: echo 'this one is valid'
 79invalid line without colon`
 80
 81		procs := Parse(strings.NewReader(input))
 82
 83		if len(procs) != 1 {
 84			t.Errorf("Expected 1 process, got %d", len(procs))
 85		}
 86
 87		if procs[0].name != "worker" {
 88			t.Errorf("Expected process name 'worker', got '%s'", procs[0].name)
 89		}
 90	})
 91
 92	t.Run("TestParseEmptyCommands", func(t *testing.T) {
 93		input := `web: 
 94worker: echo 'this is valid'
 95empty:`
 96
 97		procs := Parse(strings.NewReader(input))
 98
 99		if len(procs) != 1 {
100			t.Errorf("Expected 1 process, got %d", len(procs))
101		}
102
103		if procs[0].name != "worker" {
104			t.Errorf("Expected process name 'worker', got '%s'", procs[0].name)
105		}
106	})
107
108	t.Run("TestParseEnvironmentVariables", func(t *testing.T) {
109		os.Setenv("TEST_PORT", "3000")
110		os.Setenv("TEST_ENV", "development")
111		defer func() {
112			os.Unsetenv("TEST_PORT")
113			os.Unsetenv("TEST_ENV")
114		}()
115
116		input := `web: ./server -port $TEST_PORT
117worker: ./worker -env $TEST_ENV`
118
119		procs := Parse(strings.NewReader(input))
120
121		if len(procs) != 2 {
122			t.Errorf("Expected 2 processes, got %d", len(procs))
123		}
124
125		// Check that environment variables were expanded
126		webArgs := procs[0].args
127		if len(webArgs) < 3 || webArgs[2] != "3000" {
128			t.Errorf("Expected web port '3000', got args: %v", webArgs)
129		}
130
131		workerArgs := procs[1].args
132		if len(workerArgs) < 3 || workerArgs[2] != "development" {
133			t.Errorf("Expected worker env 'development', got args: %v", workerArgs)
134		}
135	})
136}
137
138func TestParseFile(t *testing.T) {
139	tests := []struct {
140		file     string
141		expected int
142	}{
143		{"testdata/valid/basic.procfile", 1},
144		{"testdata/valid/multiple.procfile", 3},
145		{"testdata/valid/with-comments.procfile", 2},
146		{"testdata/invalid/no-colon.procfile", 1},      // Only valid lines parsed
147		{"testdata/invalid/empty-command.procfile", 1}, // Only valid lines parsed
148		{"testdata/env/variables.procfile", 3},         // Environment variable expansion
149	}
150
151	for _, test := range tests {
152		t.Run(test.file, func(t *testing.T) {
153			procs, err := ParseFile(test.file)
154			if err != nil {
155				t.Fatalf("ParseFile failed: %v", err)
156			}
157
158			if len(procs) != test.expected {
159				t.Errorf("Expected %d processes, got %d", test.expected, len(procs))
160			}
161		})
162	}
163}