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}