28 changed files with 724 additions and 445 deletions
@ -0,0 +1,20 @@ |
|||||||
|
name: test_highlevel |
||||||
|
|
||||||
|
on: |
||||||
|
push: |
||||||
|
branches: [ main ] |
||||||
|
pull_request: |
||||||
|
branches: [ main ] |
||||||
|
|
||||||
|
jobs: |
||||||
|
test: |
||||||
|
runs-on: ubuntu-20.04 |
||||||
|
|
||||||
|
steps: |
||||||
|
- uses: actions/checkout@v2 |
||||||
|
|
||||||
|
- uses: actions/setup-go@v2 |
||||||
|
with: |
||||||
|
go-version: "1.19" |
||||||
|
|
||||||
|
- run: make test-highlevel-nodocker |
||||||
@ -0,0 +1,31 @@ |
|||||||
|
//go:build enable_highlevel_tests
|
||||||
|
// +build enable_highlevel_tests
|
||||||
|
|
||||||
|
package highleveltests |
||||||
|
|
||||||
|
import ( |
||||||
|
"os" |
||||||
|
"os/exec" |
||||||
|
"path/filepath" |
||||||
|
"testing" |
||||||
|
|
||||||
|
"github.com/stretchr/testify/require" |
||||||
|
) |
||||||
|
|
||||||
|
func buildImage(image string) error { |
||||||
|
ecmd := exec.Command("docker", "build", filepath.Join("images", image), |
||||||
|
"-t", "rtsp-simple-server-test-"+image) |
||||||
|
ecmd.Stdout = nil |
||||||
|
ecmd.Stderr = os.Stderr |
||||||
|
return ecmd.Run() |
||||||
|
} |
||||||
|
|
||||||
|
func TestBuildImages(t *testing.T) { |
||||||
|
files, err := os.ReadDir("images") |
||||||
|
require.NoError(t, err) |
||||||
|
|
||||||
|
for _, file := range files { |
||||||
|
err := buildImage(file.Name()) |
||||||
|
require.NoError(t, err) |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,186 @@ |
|||||||
|
//go:build enable_highlevel_tests
|
||||||
|
// +build enable_highlevel_tests
|
||||||
|
|
||||||
|
package highleveltests |
||||||
|
|
||||||
|
import ( |
||||||
|
"context" |
||||||
|
"encoding/json" |
||||||
|
"net" |
||||||
|
"net/http" |
||||||
|
"testing" |
||||||
|
"time" |
||||||
|
|
||||||
|
"github.com/gin-gonic/gin" |
||||||
|
"github.com/stretchr/testify/require" |
||||||
|
) |
||||||
|
|
||||||
|
type testHTTPAuthenticator struct { |
||||||
|
action string |
||||||
|
|
||||||
|
s *http.Server |
||||||
|
} |
||||||
|
|
||||||
|
func newTestHTTPAuthenticator(action string) (*testHTTPAuthenticator, error) { |
||||||
|
ln, err := net.Listen("tcp", "127.0.0.1:9120") |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
|
||||||
|
ts := &testHTTPAuthenticator{ |
||||||
|
action: action, |
||||||
|
} |
||||||
|
|
||||||
|
router := gin.New() |
||||||
|
router.POST("/auth", ts.onAuth) |
||||||
|
|
||||||
|
ts.s = &http.Server{Handler: router} |
||||||
|
go ts.s.Serve(ln) |
||||||
|
|
||||||
|
return ts, nil |
||||||
|
} |
||||||
|
|
||||||
|
func (ts *testHTTPAuthenticator) close() { |
||||||
|
ts.s.Shutdown(context.Background()) |
||||||
|
} |
||||||
|
|
||||||
|
func (ts *testHTTPAuthenticator) onAuth(ctx *gin.Context) { |
||||||
|
var in struct { |
||||||
|
IP string `json:"ip"` |
||||||
|
User string `json:"user"` |
||||||
|
Password string `json:"password"` |
||||||
|
Path string `json:"path"` |
||||||
|
Action string `json:"action"` |
||||||
|
Query string `json:"query"` |
||||||
|
} |
||||||
|
err := json.NewDecoder(ctx.Request.Body).Decode(&in) |
||||||
|
if err != nil { |
||||||
|
ctx.AbortWithStatus(http.StatusBadRequest) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
var user string |
||||||
|
if ts.action == "publish" { |
||||||
|
user = "testpublisher" |
||||||
|
} else { |
||||||
|
user = "testreader" |
||||||
|
} |
||||||
|
|
||||||
|
if in.IP != "127.0.0.1" || |
||||||
|
in.User != user || |
||||||
|
in.Password != "testpass" || |
||||||
|
in.Path != "teststream" || |
||||||
|
in.Action != ts.action || |
||||||
|
(in.Query != "user=testreader&pass=testpass¶m=value" && |
||||||
|
in.Query != "user=testpublisher&pass=testpass¶m=value" && |
||||||
|
in.Query != "param=value") { |
||||||
|
ctx.AbortWithStatus(http.StatusBadRequest) |
||||||
|
return |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func TestHLSServerRead(t *testing.T) { |
||||||
|
p, ok := newInstance("paths:\n" + |
||||||
|
" all:\n") |
||||||
|
require.Equal(t, true, ok) |
||||||
|
defer p.Close() |
||||||
|
|
||||||
|
cnt1, err := newContainer("ffmpeg", "source", []string{ |
||||||
|
"-re", |
||||||
|
"-stream_loop", "-1", |
||||||
|
"-i", "emptyvideo.mkv", |
||||||
|
"-c", "copy", |
||||||
|
"-f", "rtsp", |
||||||
|
"rtsp://127.0.0.1:8554/test/stream", |
||||||
|
}) |
||||||
|
require.NoError(t, err) |
||||||
|
defer cnt1.close() |
||||||
|
|
||||||
|
time.Sleep(1 * time.Second) |
||||||
|
|
||||||
|
cnt2, err := newContainer("ffmpeg", "dest", []string{ |
||||||
|
"-i", "http://127.0.0.1:8888/test/stream/index.m3u8", |
||||||
|
"-vframes", "1", |
||||||
|
"-f", "image2", |
||||||
|
"-y", "/dev/null", |
||||||
|
}) |
||||||
|
require.NoError(t, err) |
||||||
|
defer cnt2.close() |
||||||
|
require.Equal(t, 0, cnt2.wait()) |
||||||
|
} |
||||||
|
|
||||||
|
func TestHLSServerAuth(t *testing.T) { |
||||||
|
for _, mode := range []string{ |
||||||
|
"internal", |
||||||
|
"external", |
||||||
|
} { |
||||||
|
for _, result := range []string{ |
||||||
|
"success", |
||||||
|
"fail", |
||||||
|
} { |
||||||
|
t.Run(mode+"_"+result, func(t *testing.T) { |
||||||
|
var conf string |
||||||
|
if mode == "internal" { |
||||||
|
conf = "paths:\n" + |
||||||
|
" all:\n" + |
||||||
|
" readUser: testreader\n" + |
||||||
|
" readPass: testpass\n" + |
||||||
|
" readIPs: [127.0.0.0/16]\n" |
||||||
|
} else { |
||||||
|
conf = "externalAuthenticationURL: http://127.0.0.1:9120/auth\n" + |
||||||
|
"paths:\n" + |
||||||
|
" all:\n" |
||||||
|
} |
||||||
|
|
||||||
|
p, ok := newInstance(conf) |
||||||
|
require.Equal(t, true, ok) |
||||||
|
defer p.Close() |
||||||
|
|
||||||
|
var a *testHTTPAuthenticator |
||||||
|
if mode == "external" { |
||||||
|
var err error |
||||||
|
a, err = newTestHTTPAuthenticator("publish") |
||||||
|
require.NoError(t, err) |
||||||
|
} |
||||||
|
|
||||||
|
cnt1, err := newContainer("ffmpeg", "source", []string{ |
||||||
|
"-re", |
||||||
|
"-stream_loop", "-1", |
||||||
|
"-i", "emptyvideo.mkv", |
||||||
|
"-c", "copy", |
||||||
|
"-f", "rtsp", |
||||||
|
"rtsp://testpublisher:testpass@127.0.0.1:8554/teststream?param=value", |
||||||
|
}) |
||||||
|
require.NoError(t, err) |
||||||
|
defer cnt1.close() |
||||||
|
|
||||||
|
time.Sleep(1 * time.Second) |
||||||
|
|
||||||
|
if mode == "external" { |
||||||
|
a.close() |
||||||
|
var err error |
||||||
|
a, err = newTestHTTPAuthenticator("read") |
||||||
|
require.NoError(t, err) |
||||||
|
defer a.close() |
||||||
|
} |
||||||
|
|
||||||
|
var usr string |
||||||
|
if result == "success" { |
||||||
|
usr = "testreader" |
||||||
|
} else { |
||||||
|
usr = "testreader2" |
||||||
|
} |
||||||
|
|
||||||
|
res, err := http.Get("http://" + usr + ":testpass@127.0.0.1:8888/teststream/index.m3u8?param=value") |
||||||
|
require.NoError(t, err) |
||||||
|
defer res.Body.Close() |
||||||
|
|
||||||
|
if result == "success" { |
||||||
|
require.Equal(t, http.StatusOK, res.StatusCode) |
||||||
|
} else { |
||||||
|
require.Equal(t, http.StatusUnauthorized, res.StatusCode) |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,234 @@ |
|||||||
|
//go:build enable_highlevel_tests
|
||||||
|
// +build enable_highlevel_tests
|
||||||
|
|
||||||
|
package highleveltests |
||||||
|
|
||||||
|
import ( |
||||||
|
"os" |
||||||
|
"testing" |
||||||
|
"time" |
||||||
|
|
||||||
|
"github.com/stretchr/testify/require" |
||||||
|
) |
||||||
|
|
||||||
|
func TestRTSPServerPublishRead(t *testing.T) { |
||||||
|
for _, ca := range []struct { |
||||||
|
publisherSoft string |
||||||
|
publisherProto string |
||||||
|
readerSoft string |
||||||
|
readerProto string |
||||||
|
}{ |
||||||
|
{"ffmpeg", "udp", "ffmpeg", "udp"}, |
||||||
|
{"ffmpeg", "udp", "ffmpeg", "multicast"}, |
||||||
|
{"ffmpeg", "udp", "ffmpeg", "tcp"}, |
||||||
|
{"ffmpeg", "udp", "gstreamer", "udp"}, |
||||||
|
{"ffmpeg", "udp", "gstreamer", "multicast"}, |
||||||
|
{"ffmpeg", "udp", "gstreamer", "tcp"}, |
||||||
|
{"ffmpeg", "udp", "vlc", "udp"}, |
||||||
|
{"ffmpeg", "udp", "vlc", "multicast"}, |
||||||
|
{"ffmpeg", "udp", "vlc", "tcp"}, |
||||||
|
{"ffmpeg", "tcp", "ffmpeg", "udp"}, |
||||||
|
{"gstreamer", "udp", "ffmpeg", "udp"}, |
||||||
|
{"gstreamer", "tcp", "ffmpeg", "udp"}, |
||||||
|
{"ffmpeg", "tls", "ffmpeg", "tls"}, |
||||||
|
{"ffmpeg", "tls", "gstreamer", "tls"}, |
||||||
|
{"gstreamer", "tls", "ffmpeg", "tls"}, |
||||||
|
} { |
||||||
|
t.Run(ca.publisherSoft+"_"+ca.publisherProto+"_"+ |
||||||
|
ca.readerSoft+"_"+ca.readerProto, func(t *testing.T) { |
||||||
|
var proto string |
||||||
|
var port string |
||||||
|
if ca.publisherProto != "tls" { |
||||||
|
proto = "rtsp" |
||||||
|
port = "8554" |
||||||
|
|
||||||
|
p, ok := newInstance("rtmpDisable: yes\n" + |
||||||
|
"hlsDisable: yes\n" + |
||||||
|
"readTimeout: 20s\n" + |
||||||
|
"paths:\n" + |
||||||
|
" all:\n") |
||||||
|
require.Equal(t, true, ok) |
||||||
|
defer p.Close() |
||||||
|
} else { |
||||||
|
proto = "rtsps" |
||||||
|
port = "8322" |
||||||
|
|
||||||
|
serverCertFpath, err := writeTempFile(serverCert) |
||||||
|
require.NoError(t, err) |
||||||
|
defer os.Remove(serverCertFpath) |
||||||
|
|
||||||
|
serverKeyFpath, err := writeTempFile(serverKey) |
||||||
|
require.NoError(t, err) |
||||||
|
defer os.Remove(serverKeyFpath) |
||||||
|
|
||||||
|
p, ok := newInstance("rtmpDisable: yes\n" + |
||||||
|
"hlsDisable: yes\n" + |
||||||
|
"readTimeout: 20s\n" + |
||||||
|
"protocols: [tcp]\n" + |
||||||
|
"encryption: \"yes\"\n" + |
||||||
|
"serverCert: " + serverCertFpath + "\n" + |
||||||
|
"serverKey: " + serverKeyFpath + "\n" + |
||||||
|
"paths:\n" + |
||||||
|
" all:\n") |
||||||
|
require.Equal(t, true, ok) |
||||||
|
defer p.Close() |
||||||
|
} |
||||||
|
|
||||||
|
switch ca.publisherSoft { |
||||||
|
case "ffmpeg": |
||||||
|
ps := func() string { |
||||||
|
switch ca.publisherProto { |
||||||
|
case "udp", "tcp": |
||||||
|
return ca.publisherProto |
||||||
|
|
||||||
|
default: // tls
|
||||||
|
return "tcp" |
||||||
|
} |
||||||
|
}() |
||||||
|
|
||||||
|
cnt1, err := newContainer("ffmpeg", "source", []string{ |
||||||
|
"-re", |
||||||
|
"-stream_loop", "-1", |
||||||
|
"-i", "emptyvideo.mkv", |
||||||
|
"-c", "copy", |
||||||
|
"-f", "rtsp", |
||||||
|
"-rtsp_transport", |
||||||
|
ps, |
||||||
|
proto + "://localhost:" + port + "/teststream", |
||||||
|
}) |
||||||
|
require.NoError(t, err) |
||||||
|
defer cnt1.close() |
||||||
|
|
||||||
|
time.Sleep(1 * time.Second) |
||||||
|
|
||||||
|
case "gstreamer": |
||||||
|
ps := func() string { |
||||||
|
switch ca.publisherProto { |
||||||
|
case "udp", "tcp": |
||||||
|
return ca.publisherProto |
||||||
|
|
||||||
|
default: // tls
|
||||||
|
return "tcp" |
||||||
|
} |
||||||
|
}() |
||||||
|
|
||||||
|
cnt1, err := newContainer("gstreamer", "source", []string{ |
||||||
|
"filesrc location=emptyvideo.mkv ! matroskademux ! video/x-h264 ! rtspclientsink " + |
||||||
|
"location=" + proto + "://localhost:" + port + "/teststream " + |
||||||
|
"protocols=" + ps + " tls-validation-flags=0 latency=0 timeout=0 rtx-time=0", |
||||||
|
}) |
||||||
|
require.NoError(t, err) |
||||||
|
defer cnt1.close() |
||||||
|
|
||||||
|
time.Sleep(1 * time.Second) |
||||||
|
} |
||||||
|
|
||||||
|
time.Sleep(1 * time.Second) |
||||||
|
|
||||||
|
switch ca.readerSoft { |
||||||
|
case "ffmpeg": |
||||||
|
ps := func() string { |
||||||
|
switch ca.readerProto { |
||||||
|
case "udp", "tcp": |
||||||
|
return ca.publisherProto |
||||||
|
|
||||||
|
case "multicast": |
||||||
|
return "udp_multicast" |
||||||
|
|
||||||
|
default: // tls
|
||||||
|
return "tcp" |
||||||
|
} |
||||||
|
}() |
||||||
|
|
||||||
|
cnt2, err := newContainer("ffmpeg", "dest", []string{ |
||||||
|
"-rtsp_transport", ps, |
||||||
|
"-i", proto + "://localhost:" + port + "/teststream", |
||||||
|
"-vframes", "1", |
||||||
|
"-f", "image2", |
||||||
|
"-y", "/dev/null", |
||||||
|
}) |
||||||
|
require.NoError(t, err) |
||||||
|
defer cnt2.close() |
||||||
|
require.Equal(t, 0, cnt2.wait()) |
||||||
|
|
||||||
|
case "gstreamer": |
||||||
|
ps := func() string { |
||||||
|
switch ca.readerProto { |
||||||
|
case "udp", "tcp": |
||||||
|
return ca.publisherProto |
||||||
|
|
||||||
|
case "multicast": |
||||||
|
return "udp-mcast" |
||||||
|
|
||||||
|
default: // tls
|
||||||
|
return "tcp" |
||||||
|
} |
||||||
|
}() |
||||||
|
|
||||||
|
cnt2, err := newContainer("gstreamer", "read", []string{ |
||||||
|
"rtspsrc location=" + proto + "://127.0.0.1:" + port + "/teststream " + |
||||||
|
"protocols=" + ps + " " + |
||||||
|
"tls-validation-flags=0 latency=0 " + |
||||||
|
"! application/x-rtp,media=video ! decodebin ! exitafterframe ! fakesink", |
||||||
|
}) |
||||||
|
require.NoError(t, err) |
||||||
|
defer cnt2.close() |
||||||
|
require.Equal(t, 0, cnt2.wait()) |
||||||
|
|
||||||
|
case "vlc": |
||||||
|
args := []string{} |
||||||
|
if ca.readerProto == "tcp" { |
||||||
|
args = append(args, "--rtsp-tcp") |
||||||
|
} |
||||||
|
|
||||||
|
ur := proto + "://localhost:" + port + "/teststream" |
||||||
|
if ca.readerProto == "multicast" { |
||||||
|
ur += "?vlcmulticast" |
||||||
|
} |
||||||
|
|
||||||
|
args = append(args, ur) |
||||||
|
cnt2, err := newContainer("vlc", "dest", args) |
||||||
|
require.NoError(t, err) |
||||||
|
defer cnt2.close() |
||||||
|
require.Equal(t, 0, cnt2.wait()) |
||||||
|
} |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
func TestRTSPServerRedirect(t *testing.T) { |
||||||
|
p1, ok := newInstance("rtmpDisable: yes\n" + |
||||||
|
"hlsDisable: yes\n" + |
||||||
|
"paths:\n" + |
||||||
|
" path1:\n" + |
||||||
|
" source: redirect\n" + |
||||||
|
" sourceRedirect: rtsp://localhost:8554/path2\n" + |
||||||
|
" path2:\n") |
||||||
|
require.Equal(t, true, ok) |
||||||
|
defer p1.Close() |
||||||
|
|
||||||
|
cnt1, err := newContainer("ffmpeg", "source", []string{ |
||||||
|
"-re", |
||||||
|
"-stream_loop", "-1", |
||||||
|
"-i", "emptyvideo.mkv", |
||||||
|
"-c", "copy", |
||||||
|
"-f", "rtsp", |
||||||
|
"-rtsp_transport", "udp", |
||||||
|
"rtsp://localhost:8554/path2", |
||||||
|
}) |
||||||
|
require.NoError(t, err) |
||||||
|
defer cnt1.close() |
||||||
|
|
||||||
|
time.Sleep(1 * time.Second) |
||||||
|
|
||||||
|
cnt2, err := newContainer("ffmpeg", "dest", []string{ |
||||||
|
"-rtsp_transport", "udp", |
||||||
|
"-i", "rtsp://localhost:8554/path1", |
||||||
|
"-vframes", "1", |
||||||
|
"-f", "image2", |
||||||
|
"-y", "/dev/null", |
||||||
|
}) |
||||||
|
require.NoError(t, err) |
||||||
|
defer cnt2.close() |
||||||
|
require.Equal(t, 0, cnt2.wait()) |
||||||
|
} |
||||||
@ -0,0 +1,142 @@ |
|||||||
|
//go:build enable_highlevel_tests
|
||||||
|
// +build enable_highlevel_tests
|
||||||
|
|
||||||
|
package highleveltests |
||||||
|
|
||||||
|
import ( |
||||||
|
"os" |
||||||
|
"os/exec" |
||||||
|
"strconv" |
||||||
|
"time" |
||||||
|
|
||||||
|
"github.com/aler9/rtsp-simple-server/internal/core" |
||||||
|
) |
||||||
|
|
||||||
|
var serverCert = []byte(`-----BEGIN CERTIFICATE----- |
||||||
|
MIIDazCCAlOgAwIBAgIUXw1hEC3LFpTsllv7D3ARJyEq7sIwDQYJKoZIhvcNAQEL |
||||||
|
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM |
||||||
|
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDEyMTMxNzQ0NThaFw0zMDEy |
||||||
|
MTExNzQ0NThaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw |
||||||
|
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEB |
||||||
|
AQUAA4IBDwAwggEKAoIBAQDG8DyyS51810GsGwgWr5rjJK7OE1kTTLSNEEKax8Bj |
||||||
|
zOyiaz8rA2JGl2VUEpi2UjDr9Cm7nd+YIEVs91IIBOb7LGqObBh1kGF3u5aZxLkv |
||||||
|
NJE+HrLVvUhaDobK2NU+Wibqc/EI3DfUkt1rSINvv9flwTFu1qHeuLWhoySzDKEp |
||||||
|
OzYxpFhwjVSokZIjT4Red3OtFz7gl2E6OAWe2qoh5CwLYVdMWtKR0Xuw3BkDPk9I |
||||||
|
qkQKx3fqv97LPEzhyZYjDT5WvGrgZ1WDAN3booxXF3oA1H3GHQc4m/vcLatOtb8e |
||||||
|
nI59gMQLEbnp08cl873bAuNuM95EZieXTHNbwUnq5iybAgMBAAGjUzBRMB0GA1Ud |
||||||
|
DgQWBBQBKhJh8eWu0a4au9X/2fKhkFX2vjAfBgNVHSMEGDAWgBQBKhJh8eWu0a4a |
||||||
|
u9X/2fKhkFX2vjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBj |
||||||
|
3aCW0YPKukYgVK9cwN0IbVy/D0C1UPT4nupJcy/E0iC7MXPZ9D/SZxYQoAkdptdO |
||||||
|
xfI+RXkpQZLdODNx9uvV+cHyZHZyjtE5ENu/i5Rer2cWI/mSLZm5lUQyx+0KZ2Yu |
||||||
|
tEI1bsebDK30msa8QSTn0WidW9XhFnl3gRi4wRdimcQapOWYVs7ih+nAlSvng7NI |
||||||
|
XpAyRs8PIEbpDDBMWnldrX4TP6EWYUi49gCp8OUDRREKX3l6Ls1vZ02F34yHIt/7 |
||||||
|
7IV/XSKG096bhW+icKBWV0IpcEsgTzPK1J1hMxgjhzIMxGboAeUU+kidthOob6Sd |
||||||
|
XQxaORfgM//NzX9LhUPk
|
||||||
|
-----END CERTIFICATE----- |
||||||
|
`) |
||||||
|
|
||||||
|
var serverKey = []byte(`-----BEGIN RSA PRIVATE KEY----- |
||||||
|
MIIEogIBAAKCAQEAxvA8skudfNdBrBsIFq+a4ySuzhNZE0y0jRBCmsfAY8zsoms/ |
||||||
|
KwNiRpdlVBKYtlIw6/Qpu53fmCBFbPdSCATm+yxqjmwYdZBhd7uWmcS5LzSRPh6y |
||||||
|
1b1IWg6GytjVPlom6nPxCNw31JLda0iDb7/X5cExbtah3ri1oaMkswyhKTs2MaRY |
||||||
|
cI1UqJGSI0+EXndzrRc+4JdhOjgFntqqIeQsC2FXTFrSkdF7sNwZAz5PSKpECsd3 |
||||||
|
6r/eyzxM4cmWIw0+Vrxq4GdVgwDd26KMVxd6ANR9xh0HOJv73C2rTrW/HpyOfYDE |
||||||
|
CxG56dPHJfO92wLjbjPeRGYnl0xzW8FJ6uYsmwIDAQABAoIBACi0BKcyQ3HElSJC |
||||||
|
kaAao+Uvnzh4yvPg8Nwf5JDIp/uDdTMyIEWLtrLczRWrjGVZYbsVROinP5VfnPTT |
||||||
|
kYwkfKINj2u+gC6lsNuPnRuvHXikF8eO/mYvCTur1zZvsQnF5kp4GGwIqr+qoPUP |
||||||
|
bB0UMndG1PdpoMryHe+JcrvTrLHDmCeH10TqOwMsQMLHYLkowvxwJWsmTY7/Qr5S |
||||||
|
Wm3PPpOcW2i0uyPVuyuv4yD1368fqnqJ8QFsQp1K6QtYsNnJ71Hut1/IoxK/e6hj |
||||||
|
5Z+byKtHVtmcLnABuoOT7BhleJNFBksX9sh83jid4tMBgci+zXNeGmgqo2EmaWAb |
||||||
|
agQslkECgYEA8B1rzjOHVQx/vwSzDa4XOrpoHQRfyElrGNz9JVBvnoC7AorezBXQ |
||||||
|
M9WTHQIFTGMjzD8pb+YJGi3gj93VN51r0SmJRxBaBRh1ZZI9kFiFzngYev8POgD3 |
||||||
|
ygmlS3kTHCNxCK/CJkB+/jMBgtPj5ygDpCWVcTSuWlQFphePkW7jaaECgYEA1Blz |
||||||
|
ulqgAyJHZaqgcbcCsI2q6m527hVr9pjzNjIVmkwu38yS9RTCgdlbEVVDnS0hoifl |
||||||
|
+jVMEGXjF3xjyMvL50BKbQUH+KAa+V4n1WGlnZOxX9TMny8MBjEuSX2+362vQ3BX |
||||||
|
4vOlX00gvoc+sY+lrzvfx/OdPCHQGVYzoKCxhLsCgYA07HcviuIAV/HsO2/vyvhp |
||||||
|
xF5gTu+BqNUHNOZDDDid+ge+Jre2yfQLCL8VPLXIQW3Jff53IH/PGl+NtjphuLvj |
||||||
|
7UDJvgvpZZuymIojP6+2c3gJ3CASC9aR3JBnUzdoE1O9s2eaoMqc4scpe+SWtZYf |
||||||
|
3vzSZ+cqF6zrD/Rf/M35IQKBgHTU4E6ShPm09CcoaeC5sp2WK8OevZw/6IyZi78a |
||||||
|
r5Oiy18zzO97U/k6xVMy6F+38ILl/2Rn31JZDVJujniY6eSkIVsUHmPxrWoXV1HO |
||||||
|
y++U32uuSFiXDcSLarfIsE992MEJLSAynbF1Rsgsr3gXbGiuToJRyxbIeVy7gwzD |
||||||
|
94TpAoGAY4/PejWQj9psZfAhyk5dRGra++gYRQ/gK1IIc1g+Dd2/BxbT/RHr05GK |
||||||
|
6vwrfjsoRyMWteC1SsNs/CurjfQ/jqCfHNP5XPvxgd5Ec8sRJIiV7V5RTuWJsPu1 |
||||||
|
+3K6cnKEyg+0ekYmLertRFIY6SwWmY1fyKgTvxudMcsBY7dC4xs= |
||||||
|
-----END RSA PRIVATE KEY----- |
||||||
|
`) |
||||||
|
|
||||||
|
func writeTempFile(byts []byte) (string, error) { |
||||||
|
tmpf, err := os.CreateTemp(os.TempDir(), "rtsp-") |
||||||
|
if err != nil { |
||||||
|
return "", err |
||||||
|
} |
||||||
|
defer tmpf.Close() |
||||||
|
|
||||||
|
_, err = tmpf.Write(byts) |
||||||
|
if err != nil { |
||||||
|
return "", err |
||||||
|
} |
||||||
|
|
||||||
|
return tmpf.Name(), nil |
||||||
|
} |
||||||
|
|
||||||
|
func newInstance(conf string) (*core.Core, bool) { |
||||||
|
if conf == "" { |
||||||
|
return core.New([]string{}) |
||||||
|
} |
||||||
|
|
||||||
|
tmpf, err := writeTempFile([]byte(conf)) |
||||||
|
if err != nil { |
||||||
|
return nil, false |
||||||
|
} |
||||||
|
defer os.Remove(tmpf) |
||||||
|
|
||||||
|
return core.New([]string{tmpf}) |
||||||
|
} |
||||||
|
|
||||||
|
type container struct { |
||||||
|
name string |
||||||
|
} |
||||||
|
|
||||||
|
func newContainer(image string, name string, args []string) (*container, error) { |
||||||
|
c := &container{ |
||||||
|
name: name, |
||||||
|
} |
||||||
|
|
||||||
|
exec.Command("docker", "kill", "rtsp-simple-server-test-"+name).Run() |
||||||
|
exec.Command("docker", "wait", "rtsp-simple-server-test-"+name).Run() |
||||||
|
|
||||||
|
// --network=host is needed to test multicast
|
||||||
|
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 = nil |
||||||
|
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() int { |
||||||
|
exec.Command("docker", "wait", "rtsp-simple-server-test-"+c.name).Run() |
||||||
|
out, _ := exec.Command("docker", "inspect", "rtsp-simple-server-test-"+c.name, |
||||||
|
"-f", "{{.State.ExitCode}}").Output() |
||||||
|
code, _ := strconv.ParseInt(string(out[:len(out)-1]), 10, 64) |
||||||
|
return int(code) |
||||||
|
} |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
test-highlevel-nodocker: |
||||||
|
go test -v -race -tags enable_highlevel_tests ./internal/highleveltests |
||||||
|
|
||||||
|
define DOCKERFILE_HIGHLEVEL_TEST |
||||||
|
FROM $(BASE_IMAGE) |
||||||
|
RUN apk add --no-cache make docker-cli gcc musl-dev |
||||||
|
WORKDIR /s |
||||||
|
COPY go.mod go.sum ./ |
||||||
|
RUN go mod download |
||||||
|
COPY . ./ |
||||||
|
endef |
||||||
|
export DOCKERFILE_HIGHLEVEL_TEST |
||||||
|
|
||||||
|
test-highlevel: |
||||||
|
echo "$$DOCKERFILE_HIGHLEVEL_TEST" | docker build -q . -f - -t temp |
||||||
|
docker run --rm -it \
|
||||||
|
-v /var/run/docker.sock:/var/run/docker.sock:ro \
|
||||||
|
--network=host \
|
||||||
|
temp \
|
||||||
|
make test-highlevel-nodocker |
||||||
Loading…
Reference in new issue