Skip to content

Commit 4c33fdf

Browse files
committed
Added more test cases
1 parent 565cce8 commit 4c33fdf

2 files changed

Lines changed: 366 additions & 1 deletion

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ run:
1414
test:
1515
@echo "Running tests and generating coverage report..."
1616
@mkdir -p coverage
17-
docker compose run --rm --build -v $(PWD)/coverage:/app/coverage test go test -v -coverprofile=coverage/coverage.out ./...
17+
docker compose run --rm --build -v $(PWD)/coverage:/app/coverage test go test -coverprofile=coverage/coverage.out ./...
1818
docker compose run --rm -v $(PWD)/coverage:/app/coverage test go tool cover -html=coverage/coverage.out -o coverage/coverage.html
1919
@echo "Coverage report generated in coverage/coverage.html"
2020

cmd/main_test.go

Lines changed: 365 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,365 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"net/http"
7+
"net/http/httptest"
8+
"os/exec"
9+
"testing"
10+
11+
"go.uber.org/zap"
12+
13+
"github.com/Zozman/stream-webpage-container/utils"
14+
)
15+
16+
// Helper function to reset global stream state for testing
17+
func resetGlobalStreamState() {
18+
globalStreamState.mu.Lock()
19+
defer globalStreamState.mu.Unlock()
20+
globalStreamState.isRunning = false
21+
globalStreamState.cancelFunc = nil
22+
globalStreamState.chromeCancel = nil
23+
globalStreamState.ffmpegCmd = nil
24+
}
25+
26+
func TestRestartStream(t *testing.T) {
27+
t.Cleanup(resetGlobalStreamState)
28+
29+
t.Run("Restart Stream Successfully", func(t *testing.T) {
30+
logger, _ := zap.NewDevelopment()
31+
ctx := utils.SaveLoggerToContext(context.Background(), logger)
32+
33+
config := &Config{
34+
WebpageURL: "https://example.com",
35+
RTMPURL: "rtmp://example.com/live/stream",
36+
Resolution: "720p",
37+
Framerate: "30",
38+
Width: 1280,
39+
Height: 720,
40+
}
41+
42+
err := RestartStream(ctx, config)
43+
44+
if err != nil {
45+
t.Errorf("Expected no error, got %v", err)
46+
}
47+
})
48+
}
49+
50+
func TestIsStreamRunning(t *testing.T) {
51+
t.Cleanup(resetGlobalStreamState)
52+
53+
t.Run("Stream Not Running Initially", func(t *testing.T) {
54+
resetGlobalStreamState()
55+
56+
if IsStreamRunning() {
57+
t.Error("Expected stream to not be running initially")
58+
}
59+
})
60+
61+
t.Run("Stream Running After Setting Global State", func(t *testing.T) {
62+
resetGlobalStreamState()
63+
64+
_, cancel := context.WithCancel(context.Background())
65+
defer cancel()
66+
67+
_, chromeCancel := context.WithCancel(context.Background())
68+
defer chromeCancel()
69+
70+
mockCmd := &exec.Cmd{}
71+
globalStreamState.setStreamRunning(cancel, chromeCancel, mockCmd)
72+
73+
if !IsStreamRunning() {
74+
t.Error("Expected stream to be running after setting global state")
75+
}
76+
})
77+
}
78+
79+
func TestStopCurrentStream(t *testing.T) {
80+
t.Cleanup(resetGlobalStreamState)
81+
82+
t.Run("Stop Current Stream", func(t *testing.T) {
83+
logger, _ := zap.NewDevelopment()
84+
ctx := utils.SaveLoggerToContext(context.Background(), logger)
85+
86+
// Set up a running stream
87+
_, cancel := context.WithCancel(context.Background())
88+
_, chromeCancel := context.WithCancel(context.Background())
89+
mockCmd := &exec.Cmd{}
90+
globalStreamState.setStreamRunning(cancel, chromeCancel, mockCmd)
91+
92+
if !globalStreamState.isRunning {
93+
t.Fatal("Expected stream to be running before stopping")
94+
}
95+
96+
StopCurrentStream(ctx)
97+
98+
if globalStreamState.isRunning {
99+
t.Error("Expected stream to be stopped after calling StopCurrentStream")
100+
}
101+
})
102+
}
103+
104+
func TestLoadConfig(t *testing.T) {
105+
t.Run("Default Configuration", func(t *testing.T) {
106+
t.Setenv("WEBPAGE_URL", "")
107+
t.Setenv("RTMP_URL", "")
108+
t.Setenv("RESOLUTION", "")
109+
t.Setenv("FRAMERATE", "")
110+
111+
logger, _ := zap.NewDevelopment()
112+
ctx := utils.SaveLoggerToContext(context.Background(), logger)
113+
114+
config, err := loadConfig(ctx)
115+
116+
if err != nil {
117+
t.Fatalf("Expected no error, got %v", err)
118+
}
119+
if config.WebpageURL != DefaultWebpageURL {
120+
t.Errorf("Expected default webpage URL %q, got %q", DefaultWebpageURL, config.WebpageURL)
121+
}
122+
if config.RTMPURL != DefaultRTMPURL {
123+
t.Errorf("Expected default RTMP URL %q, got %q", DefaultRTMPURL, config.RTMPURL)
124+
}
125+
if config.Resolution != DefaultResolution {
126+
t.Errorf("Expected default resolution %q, got %q", DefaultResolution, config.Resolution)
127+
}
128+
if config.Framerate != DefaultFramerate {
129+
t.Errorf("Expected default framerate %q, got %q", DefaultFramerate, config.Framerate)
130+
}
131+
})
132+
133+
t.Run("Custom Configuration", func(t *testing.T) {
134+
expectedURL := "https://custom.example.com"
135+
expectedRTMP := "rtmp://custom.example.com/live/test"
136+
expectedResolution := "1080p"
137+
expectedFramerate := "60"
138+
139+
t.Setenv("WEBPAGE_URL", expectedURL)
140+
t.Setenv("RTMP_URL", expectedRTMP)
141+
t.Setenv("RESOLUTION", expectedResolution)
142+
t.Setenv("FRAMERATE", expectedFramerate)
143+
144+
logger, _ := zap.NewDevelopment()
145+
ctx := utils.SaveLoggerToContext(context.Background(), logger)
146+
147+
config, err := loadConfig(ctx)
148+
149+
if err != nil {
150+
t.Fatalf("Expected no error, got %v", err)
151+
}
152+
if config.WebpageURL != expectedURL {
153+
t.Errorf("Expected webpage URL %q, got %q", expectedURL, config.WebpageURL)
154+
}
155+
if config.RTMPURL != expectedRTMP {
156+
t.Errorf("Expected RTMP URL %q, got %q", expectedRTMP, config.RTMPURL)
157+
}
158+
if config.Resolution != expectedResolution {
159+
t.Errorf("Expected resolution %q, got %q", expectedResolution, config.Resolution)
160+
}
161+
if config.Framerate != expectedFramerate {
162+
t.Errorf("Expected framerate %q, got %q", expectedFramerate, config.Framerate)
163+
}
164+
})
165+
166+
t.Run("720p Resolution Dimensions", func(t *testing.T) {
167+
t.Setenv("RESOLUTION", "720p")
168+
169+
logger, _ := zap.NewDevelopment()
170+
ctx := utils.SaveLoggerToContext(context.Background(), logger)
171+
172+
config, err := loadConfig(ctx)
173+
174+
if err != nil {
175+
t.Fatalf("Expected no error, got %v", err)
176+
}
177+
if config.Width != 1280 || config.Height != 720 {
178+
t.Errorf("Expected 720p dimensions 1280x720, got %dx%d", config.Width, config.Height)
179+
}
180+
})
181+
182+
t.Run("1080p Resolution Dimensions", func(t *testing.T) {
183+
t.Setenv("RESOLUTION", "1080p")
184+
185+
logger, _ := zap.NewDevelopment()
186+
ctx := utils.SaveLoggerToContext(context.Background(), logger)
187+
188+
config, err := loadConfig(ctx)
189+
190+
if err != nil {
191+
t.Fatalf("Expected no error, got %v", err)
192+
}
193+
if config.Width != 1920 || config.Height != 1080 {
194+
t.Errorf("Expected 1080p dimensions 1920x1080, got %dx%d", config.Width, config.Height)
195+
}
196+
})
197+
198+
t.Run("2k Resolution Dimensions", func(t *testing.T) {
199+
t.Setenv("RESOLUTION", "2k")
200+
201+
logger, _ := zap.NewDevelopment()
202+
ctx := utils.SaveLoggerToContext(context.Background(), logger)
203+
204+
config, err := loadConfig(ctx)
205+
206+
if err != nil {
207+
t.Fatalf("Expected no error, got %v", err)
208+
}
209+
if config.Width != 2560 || config.Height != 1440 {
210+
t.Errorf("Expected 2K dimensions 2560x1440, got %dx%d", config.Width, config.Height)
211+
}
212+
})
213+
214+
t.Run("Invalid Resolution Defaults To 720p", func(t *testing.T) {
215+
t.Setenv("RESOLUTION", "invalid_resolution")
216+
217+
logger, _ := zap.NewDevelopment()
218+
ctx := utils.SaveLoggerToContext(context.Background(), logger)
219+
220+
config, err := loadConfig(ctx)
221+
222+
if err != nil {
223+
t.Fatalf("Expected no error, got %v", err)
224+
}
225+
if config.Resolution != "720p" {
226+
t.Errorf("Expected resolution to default to 720p, got %q", config.Resolution)
227+
}
228+
if config.Width != 1280 || config.Height != 720 {
229+
t.Errorf("Expected 720p dimensions 1280x720, got %dx%d", config.Width, config.Height)
230+
}
231+
})
232+
233+
t.Run("Invalid Framerate Defaults To 30", func(t *testing.T) {
234+
t.Setenv("FRAMERATE", "invalid_framerate")
235+
236+
logger, _ := zap.NewDevelopment()
237+
ctx := utils.SaveLoggerToContext(context.Background(), logger)
238+
239+
config, err := loadConfig(ctx)
240+
241+
if err != nil {
242+
t.Fatalf("Expected no error, got %v", err)
243+
}
244+
if config.Framerate != "30" {
245+
t.Errorf("Expected framerate to default to 30, got %q", config.Framerate)
246+
}
247+
})
248+
249+
t.Run("Valid Framerate Values", func(t *testing.T) {
250+
testCases := []string{"30", "60"}
251+
252+
for _, framerate := range testCases {
253+
t.Run("Framerate "+framerate, func(t *testing.T) {
254+
t.Setenv("FRAMERATE", framerate)
255+
256+
logger, _ := zap.NewDevelopment()
257+
ctx := utils.SaveLoggerToContext(context.Background(), logger)
258+
259+
config, err := loadConfig(ctx)
260+
261+
if err != nil {
262+
t.Fatalf("Expected no error, got %v", err)
263+
}
264+
if config.Framerate != framerate {
265+
t.Errorf("Expected framerate %q, got %q", framerate, config.Framerate)
266+
}
267+
})
268+
}
269+
})
270+
}
271+
272+
func TestGetHealthResponse(t *testing.T) {
273+
t.Run("Health Response Structure", func(t *testing.T) {
274+
req := httptest.NewRequest("GET", "/health", nil)
275+
w := httptest.NewRecorder()
276+
277+
getHealthResponse(w, req)
278+
279+
if w.Code != http.StatusOK {
280+
t.Errorf("Expected status code 200, got %d", w.Code)
281+
}
282+
283+
contentType := w.Header().Get("Content-Type")
284+
if contentType != "application/json" {
285+
t.Errorf("Expected content type application/json, got %q", contentType)
286+
}
287+
288+
var health Health
289+
if err := json.Unmarshal(w.Body.Bytes(), &health); err != nil {
290+
t.Fatalf("Failed to unmarshal health response: %v", err)
291+
}
292+
293+
if health.Message != "OK" {
294+
t.Errorf("Expected message 'OK', got %q", health.Message)
295+
}
296+
297+
if health.Uptime <= 0 {
298+
t.Error("Expected uptime to be greater than 0")
299+
}
300+
301+
if health.Date.IsZero() {
302+
t.Error("Expected date to be set")
303+
}
304+
})
305+
}
306+
307+
func TestExtractNumberFromBitrate(t *testing.T) {
308+
t.Run("Valid Bitrate Strings", func(t *testing.T) {
309+
testCases := []struct {
310+
input string
311+
expected int
312+
}{
313+
{"3000k", 3000},
314+
{"4500k", 4500},
315+
{"6000k", 6000},
316+
{"8500k", 8500},
317+
{"1000k", 1000},
318+
}
319+
320+
for _, tc := range testCases {
321+
t.Run("Bitrate "+tc.input, func(t *testing.T) {
322+
result := extractNumberFromBitrate(tc.input)
323+
if result != tc.expected {
324+
t.Errorf("Expected %d, got %d", tc.expected, result)
325+
}
326+
})
327+
}
328+
})
329+
330+
t.Run("Invalid Bitrate String", func(t *testing.T) {
331+
result := extractNumberFromBitrate("invalidk")
332+
if result != 3000 {
333+
t.Errorf("Expected default value 3000, got %d", result)
334+
}
335+
})
336+
}
337+
338+
func TestGetDisplayInfo(t *testing.T) {
339+
t.Run("Display From Environment Variable", func(t *testing.T) {
340+
expectedDisplay := ":1"
341+
t.Setenv("DISPLAY", expectedDisplay)
342+
343+
display, err := getDisplayInfo()
344+
345+
if err != nil {
346+
t.Fatalf("Expected no error, got %v", err)
347+
}
348+
if display != expectedDisplay {
349+
t.Errorf("Expected display %q, got %q", expectedDisplay, display)
350+
}
351+
})
352+
353+
t.Run("Default Display When Environment Variable Not Set", func(t *testing.T) {
354+
t.Setenv("DISPLAY", "")
355+
356+
display, err := getDisplayInfo()
357+
358+
if err != nil {
359+
t.Fatalf("Expected no error, got %v", err)
360+
}
361+
if display != ":0" {
362+
t.Errorf("Expected default display ':0', got %q", display)
363+
}
364+
})
365+
}

0 commit comments

Comments
 (0)