28 changed files with 724 additions and 445 deletions
@ -0,0 +1,20 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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