diff --git a/.travis.yml b/.travis.yml index fe7d1ec6..0750559f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ services: - docker script: +- make test - make release deploy: diff --git a/Makefile b/Makefile index 0dfd6777..6d3f8c87 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ .PHONY: $(shell ls) -BASE_IMAGE = amd64/golang:1.13-alpine3.10 +BASE_IMAGE = amd64/golang:1.14-alpine3.11 help: @echo "usage: make [action]" @@ -15,6 +15,12 @@ help: @echo " travis-setup setup travis CI" @echo "" +blank := +define NL + +$(blank) +endef + mod-tidy: docker run --rm -it -v $(PWD):/s $(BASE_IMAGE) \ sh -c "apk add git && cd /s && GOPROXY=direct go get && GOPROXY=direct go mod tidy" @@ -41,6 +47,30 @@ run: temp \ /out $(ARGS) +define DOCKERFILE_TEST +FROM $(BASE_IMAGE) +RUN apk add --no-cache make docker-cli git +WORKDIR /s +COPY go.mod go.sum ./ +RUN go mod download +COPY . ./ +endef +export DOCKERFILE_TEST + +test: + echo "$$DOCKERFILE_TEST" | docker build -q . -f - -t temp + docker run --rm -it \ + --network=host \ + -v /var/run/docker.sock:/var/run/docker.sock:ro \ + temp \ + make test-nodocker + +test-nodocker: + $(foreach IMG,$(shell echo test-images/*/ | xargs -n1 basename), \ + docker build -q test-images/$(IMG) -t rtsp-simple-server-test-$(IMG)$(NL)) + $(eval export CGO_ENABLED = 0) + go test -v . + define DOCKERFILE_RELEASE FROM $(BASE_IMAGE) RUN apk add --no-cache zip make git tar diff --git a/main.go b/main.go index 496e2044..c2a83768 100644 --- a/main.go +++ b/main.go @@ -65,23 +65,24 @@ type program struct { } func newProgram(args args) (*program, error) { + if args.protocolsStr == "" { + args.protocolsStr = "udp,tcp" + } + if args.rtspPort == 0 { + args.rtspPort = 8554 + } + if args.rtpPort == 0 { + args.rtpPort = 8000 + } + if args.rtcpPort == 0 { + args.rtcpPort = 8001 + } + if args.version == true { fmt.Println("rtsp-simple-server " + Version) os.Exit(0) } - if args.rtspPort == 0 { - return nil, fmt.Errorf("rtsp port not provided") - } - - if args.rtpPort == 0 { - return nil, fmt.Errorf("rtp port not provided") - } - - if args.rtcpPort == 0 { - return nil, fmt.Errorf("rtcp port not provided") - } - if (args.rtpPort % 2) != 0 { return nil, fmt.Errorf("rtp port must be even") } diff --git a/main_test.go b/main_test.go new file mode 100644 index 00000000..c2d622cc --- /dev/null +++ b/main_test.go @@ -0,0 +1,146 @@ +package main + +import ( + "bytes" + "os" + "os/exec" + "testing" + "time" + + "github.com/stretchr/testify/require" +) + +type container struct { + name string + stdout *bytes.Buffer +} + +func newContainer(image string, name string, args []string) (*container, error) { + c := &container{ + name: name, + stdout: bytes.NewBuffer(nil), + } + + exec.Command("docker", "kill", "rtsp-simple-server-test-"+name).Run() + exec.Command("docker", "wait", "rtsp-simple-server-test-"+name).Run() + + cmd := []string{"docker", "run", "--network=host", + "--name=rtsp-simple-server-test-" + name, + "rtsp-simple-server-test-" + image} + cmd = append(cmd, args...) + ecmd := exec.Command(cmd[0], cmd[1:]...) + + ecmd.Stdout = c.stdout + ecmd.Stderr = os.Stderr + + err := ecmd.Start() + if err != nil { + return nil, err + } + + time.Sleep(1 * time.Second) + + return c, nil +} + +func (c *container) close() { + exec.Command("docker", "kill", "rtsp-simple-server-test-"+c.name).Run() + exec.Command("docker", "wait", "rtsp-simple-server-test-"+c.name).Run() + exec.Command("docker", "rm", "rtsp-simple-server-test-"+c.name).Run() +} + +func (c *container) wait() { + exec.Command("docker", "wait", "rtsp-simple-server-test-"+c.name).Run() +} + +func TestProtocols(t *testing.T) { + for _, pair := range [][2]string{ + {"udp", "udp"}, + {"udp", "tcp"}, + {"tcp", "udp"}, + {"tcp", "tcp"}, + } { + t.Run(pair[0]+"_"+pair[1], func(t *testing.T) { + p, err := newProgram(args{}) + require.NoError(t, err) + defer p.close() + + time.Sleep(1 * time.Second) + + cnt1, err := newContainer("ffmpeg", "source", []string{ + "-hide_banner", + "-loglevel", "panic", + "-re", + "-stream_loop", "-1", + "-i", "/emptyvideo.ts", + "-c", "copy", + "-f", "rtsp", + "-rtsp_transport", pair[0], + "rtsp://localhost:8554/teststream", + }) + require.NoError(t, err) + defer cnt1.close() + + time.Sleep(1 * time.Second) + + cnt2, err := newContainer("ffmpeg", "dest", []string{ + "-hide_banner", + "-loglevel", "panic", + "-rtsp_transport", pair[1], + "-i", "rtsp://localhost:8554/teststream", + "-vframes", "1", + "-f", "image2", + "-y", "/dev/null", + }) + require.NoError(t, err) + defer cnt2.close() + + cnt2.wait() + + require.Equal(t, "all right\n", string(cnt2.stdout.Bytes())) + }) + } +} + +func TestAuthentication(t *testing.T) { + p, err := newProgram(args{ + publishUser: "testuser", + publishPass: "testpass", + }) + require.NoError(t, err) + defer p.close() + + time.Sleep(1 * time.Second) + + cnt1, err := newContainer("ffmpeg", "source", []string{ + "-hide_banner", + "-loglevel", "panic", + "-re", + "-stream_loop", "-1", + "-i", "/emptyvideo.ts", + "-c", "copy", + "-f", "rtsp", + "-rtsp_transport", "udp", + "rtsp://testuser:testpass@localhost:8554/teststream", + }) + require.NoError(t, err) + defer cnt1.close() + + time.Sleep(1 * time.Second) + + cnt2, err := newContainer("ffmpeg", "dest", []string{ + "-hide_banner", + "-loglevel", "panic", + "-rtsp_transport", "udp", + "-i", "rtsp://localhost:8554/teststream", + "-vframes", "1", + "-f", "image2", + "-y", "/dev/null", + }) + require.NoError(t, err) + defer cnt2.close() + + cnt2.wait() + + require.Equal(t, "all right\n", string(cnt2.stdout.Bytes())) +} diff --git a/test-images/ffmpeg/Dockerfile b/test-images/ffmpeg/Dockerfile new file mode 100644 index 00000000..67312444 --- /dev/null +++ b/test-images/ffmpeg/Dockerfile @@ -0,0 +1,11 @@ +FROM amd64/alpine:3.11 + +RUN apk add --no-cache \ + ffmpeg + +COPY emptyvideo.ts / + +COPY start.sh / +RUN chmod +x /start.sh + +ENTRYPOINT [ "/start.sh" ] diff --git a/test-images/ffmpeg/emptyvideo.ts b/test-images/ffmpeg/emptyvideo.ts new file mode 100644 index 00000000..6693c037 Binary files /dev/null and b/test-images/ffmpeg/emptyvideo.ts differ diff --git a/test-images/ffmpeg/start.sh b/test-images/ffmpeg/start.sh new file mode 100644 index 00000000..75fddf35 --- /dev/null +++ b/test-images/ffmpeg/start.sh @@ -0,0 +1,5 @@ +#!/bin/sh -e + +ffmpeg $@ + +echo "all right"