0

Allow HLS test to wait for stream changes

This commit is contained in:
Gabe Kangas 2023-01-22 21:07:49 -08:00
parent f4ed7d7453
commit 57beaacd2c
No known key found for this signature in database
GPG Key ID: 4345B2060657F330
3 changed files with 92 additions and 83 deletions

View File

@ -28,5 +28,10 @@ jobs:
- uses: actions/setup-go@v3
with:
go-version: '1.18.8'
- name: Run HLS tests
run: cd test/automated/hls && ./run.sh
uses: nick-fields/retry@v2
with:
timeout_minutes: 10
max_attempts: 3
command: cd test/automated/hls && ./run.sh

View File

@ -11,112 +11,112 @@ const HLS_FETCH_ITERATIONS = 5;
jest.setTimeout(40000);
async function getPlaylist(urlString) {
const response = await fetch(urlString);
expect(response.status).toBe(200);
const body = await response.text();
const response = await fetch(urlString);
expect(response.status).toBe(200);
const body = await response.text();
var parser = new m3u8Parser.Parser();
var parser = new m3u8Parser.Parser();
parser.push(body);
parser.end();
parser.push(body);
parser.end();
return parser.manifest;
return parser.manifest;
}
function normalizeUrl(urlString, baseUrl) {
let parsedString = url.parse(urlString);
if (!parsedString.host) {
const testInstanceRoot = url.parse(baseUrl);
parsedString.protocol = testInstanceRoot.protocol;
parsedString.host = testInstanceRoot.host;
let parsedString = url.parse(urlString);
if (!parsedString.host) {
const testInstanceRoot = url.parse(baseUrl);
parsedString.protocol = testInstanceRoot.protocol;
parsedString.host = testInstanceRoot.host;
const filename = baseUrl.substring(baseUrl.lastIndexOf('/') + 1);
parsedString.pathname =
testInstanceRoot.pathname.replace(filename, '') + urlString;
}
return url.format(parsedString).toString();
const filename = baseUrl.substring(baseUrl.lastIndexOf('/') + 1);
parsedString.pathname =
testInstanceRoot.pathname.replace(filename, '') + urlString;
}
return url.format(parsedString).toString();
}
// Iterate over an array of video segments and make sure they return back
// valid status.
async function validateSegments(segments) {
for (let segment of segments) {
const res = await fetch(segment);
expect(res.status).toBe(200);
}
for (let segment of segments) {
const res = await fetch(segment);
expect(res.status).toBe(200);
}
}
describe('fetch and parse HLS', () => {
const masterPlaylistUrl = `${TEST_OWNCAST_INSTANCE}${HLS_SUBDIRECTORY}${PLAYLIST_NAME}`;
var masterPlaylist;
var mediaPlaylistUrl;
const masterPlaylistUrl = `${TEST_OWNCAST_INSTANCE}${HLS_SUBDIRECTORY}${PLAYLIST_NAME}`;
var masterPlaylist;
var mediaPlaylistUrl;
test('fetch master playlist', async (done) => {
try {
masterPlaylist = await getPlaylist(masterPlaylistUrl);
} catch (e) {
console.error('error fetching and parsing master playlist', e);
}
test('fetch master playlist', async (done) => {
try {
masterPlaylist = await getPlaylist(masterPlaylistUrl);
} catch (e) {
console.error('error fetching and parsing master playlist', e);
}
done();
});
done();
});
test('verify there is a media playlist', () => {
// Master playlist should have at least one media playlist.
expect(masterPlaylist.playlists.length).toBe(1);
test('verify there is a media playlist', () => {
// Master playlist should have at least one media playlist.
expect(masterPlaylist.playlists.length).toBe(1);
try {
mediaPlaylistUrl = normalizeUrl(
masterPlaylist.playlists[0].uri,
masterPlaylistUrl
);
} catch (e) {
console.error('error fetching and parsing media playlist', e);
}
});
try {
mediaPlaylistUrl = normalizeUrl(
masterPlaylist.playlists[0].uri,
masterPlaylistUrl
);
} catch (e) {
console.error('error fetching and parsing media playlist', e);
}
});
test('verify there are segments', async (done) => {
let playlist;
try {
playlist = await getPlaylist(mediaPlaylistUrl);
} catch (e) {
console.error('error verifying segments in media playlist', e);
}
test('verify there are segments', async (done) => {
let playlist;
try {
playlist = await getPlaylist(mediaPlaylistUrl);
} catch (e) {
console.error('error verifying segments in media playlist', e);
}
const segments = playlist.segments;
expect(segments.length).toBeGreaterThan(0);
const segments = playlist.segments;
expect(segments.length).toBeGreaterThan(0);
done();
});
done();
});
// Iterate over segments and make sure they change.
// Use the reported duration of the segment to wait to
// fetch another just like a real HLS player would do.
var lastSegmentUrl;
for (let i = 0; i < HLS_FETCH_ITERATIONS; i++) {
test('fetch and monitor media playlist segments ' + i, async (done) => {
await new Promise((r) => setTimeout(r, 3000));
// Iterate over segments and make sure they change.
// Use the reported duration of the segment to wait to
// fetch another just like a real HLS player would do.
var lastSegmentUrl;
for (let i = 0; i < HLS_FETCH_ITERATIONS; i++) {
test('fetch and monitor media playlist segments ' + i, async (done) => {
await new Promise((r) => setTimeout(r, 5000));
try {
var playlist = await getPlaylist(mediaPlaylistUrl);
} catch (e) {
console.error('error updating media playlist', mediaPlaylistUrl, e);
}
try {
var playlist = await getPlaylist(mediaPlaylistUrl);
} catch (e) {
console.error('error updating media playlist', mediaPlaylistUrl, e);
}
const segments = playlist.segments;
const segment = segments[segments.length - 1];
expect(segment.uri).not.toBe(lastSegmentUrl);
const segments = playlist.segments;
const segment = segments[segments.length - 1];
expect(segment.uri).not.toBe(lastSegmentUrl);
try {
var segmentUrl = normalizeUrl(segment.uri, mediaPlaylistUrl);
await validateSegments([segmentUrl]);
} catch (e) {
console.error('unable to validate HLS segment', segmentUrl, e);
}
try {
var segmentUrl = normalizeUrl(segment.uri, mediaPlaylistUrl);
await validateSegments([segmentUrl]);
} catch (e) {
console.error('unable to validate HLS segment', segmentUrl, e);
}
lastSegmentUrl = segment.uri;
lastSegmentUrl = segment.uri;
done();
});
}
done();
});
}
});

View File

@ -13,6 +13,8 @@ start_owncast
start_stream
sleep 10
# Run tests against a fresh install with no settings.
npm test
@ -21,8 +23,8 @@ kill_with_kids "$STREAM_PID"
# Determine if we should continue testing with S3 configuration.
if [[ -z "${S3_BUCKET}" ]]; then
echo "No S3 configuration is set. Skipping S3 tests!"
exit 0
echo "No S3 configuration is set. Skipping S3 tests!"
exit 0
fi
# Update the server config to use S3 for storage.
@ -30,5 +32,7 @@ update_storage_config
start_stream
sleep 10
# Re-run the HLS test against the external storage configuration.
npm test