From a8e2d39d6614df7f425df0bf74bcffe8a05db21c Mon Sep 17 00:00:00 2001 From: Daniel Silhavy Date: Thu, 11 Apr 2024 18:42:37 +0200 Subject: [PATCH] Fix/tests (#4451) * WiP: Minor fixes to the functional tests * Restructure functional test execution * Fix some functional tests * Add broadpeak to contributors in reference UI * Add progress reporter for browserstack tests * Use mocha in functional tests as reporter * Change multiperiod stream in smoke vectors --- .circleci/config.yml | 26 +- package.json | 2 +- .../app/contributors.json | 5 + .../app/img/broadpeak.png | Bin 0 -> 58464 bytes .../dash-if-reference-player/app/sources.json | 2 +- test/functional/adapter/DashJsAdapter.js | 2 +- .../config/karma.functional.conf.cjs | 38 +- .../test-configurations/browserstack.json | 10 + .../browserstack/drm_emsg_eptdelta_gaps.json | 161 ------- .../multiperiod_subtitle_vendor.json | 240 ---------- .../browserstack/single.json | 27 -- .../browserstack/smoke.json | 167 ------- .../vod_live_lowlatency_mss_multiaudio.json | 65 --- .../config/test-configurations/local.json | 11 + .../test-configurations/local/single.json | 39 -- .../{local => streams}/all.json | 424 +++++++----------- .../drm_emsg_eptdelta_gaps.json | 21 +- .../multiperiod_subtitle_vendor.json | 41 +- .../test-configurations/streams/single.json | 20 + .../{local => streams}/smoke.json | 12 +- .../{local => streams}/text.json | 41 +- .../vod_live_lowlatency_mss_multiaudio.json | 3 - test/functional/src/Constants.js | 2 +- .../playback-advanced/attach-at-non-zero.js | 3 +- .../playback-advanced/attach-with-posix.js | 2 - .../functional/test/playback-advanced/cmcd.js | 6 +- test/functional/test/text/initial-text.js | 2 +- 27 files changed, 289 insertions(+), 1083 deletions(-) create mode 100644 samples/dash-if-reference-player/app/img/broadpeak.png create mode 100644 test/functional/config/test-configurations/browserstack.json delete mode 100644 test/functional/config/test-configurations/browserstack/drm_emsg_eptdelta_gaps.json delete mode 100644 test/functional/config/test-configurations/browserstack/multiperiod_subtitle_vendor.json delete mode 100644 test/functional/config/test-configurations/browserstack/single.json delete mode 100644 test/functional/config/test-configurations/browserstack/smoke.json delete mode 100644 test/functional/config/test-configurations/browserstack/vod_live_lowlatency_mss_multiaudio.json create mode 100644 test/functional/config/test-configurations/local.json delete mode 100644 test/functional/config/test-configurations/local/single.json rename test/functional/config/test-configurations/{local => streams}/all.json (71%) rename test/functional/config/test-configurations/{local => streams}/drm_emsg_eptdelta_gaps.json (89%) rename test/functional/config/test-configurations/{local => streams}/multiperiod_subtitle_vendor.json (92%) create mode 100644 test/functional/config/test-configurations/streams/single.json rename test/functional/config/test-configurations/{local => streams}/smoke.json (92%) rename test/functional/config/test-configurations/{local => streams}/text.json (89%) rename test/functional/config/test-configurations/{local => streams}/vod_live_lowlatency_mss_multiaudio.json (97%) diff --git a/.circleci/config.yml b/.circleci/config.yml index 526ee73936..73424615d9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -85,15 +85,18 @@ commands: run_test_suite: parameters: - testconfig: - default: "" + streamsfile: + default: "single" + type: string + configfile: + default: "browserstack" type: string steps: - run: - name: Run functional tests <> + name: Run functional tests <> - <> when: always command: - node_modules/karma/bin/karma start test/functional/config/karma.functional.conf.cjs --configfile=<> + node_modules/karma/bin/karma start test/functional/config/karma.functional.conf.cjs --configfile=<> --streamsfile=<> build_samples: # parameters: # samples: @@ -155,9 +158,11 @@ jobs: - run_testbuild - functional_test_setup - run_test_suite: - testconfig: browserstack/single + streamsfile: single + configfile: browserstack - run_test_suite: - testconfig: browserstack/smoke + streamsfile: smoke + configfile: browserstack - process_test_results functional-tests-full-part-1: @@ -165,7 +170,8 @@ jobs: steps: - functional_steps - run_test_suite: - testconfig: browserstack/drm_emsg_eptdelta_gaps + streamsfile: drm_emsg_eptdelta_gaps + configfile: browserstack - process_test_results functional-tests-full-part-2: @@ -173,7 +179,8 @@ jobs: steps: - functional_steps - run_test_suite: - testconfig: browserstack/multiperiod_subtitle_vendor + streamsfile: multiperiod_subtitle_vendor + configfile: browserstack - process_test_results functional-tests-full-part-3: @@ -181,7 +188,8 @@ jobs: steps: - functional_steps - run_test_suite: - testconfig: browserstack/vod_live_lowlatency_mss_multiaudio + streamsfile: vod_live_lowlatency_mss_multiaudio + configfile: browserstack - process_test_results workflows: diff --git a/package.json b/package.json index 056e5dce53..feb21c9229 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "build": "tsc && npm run test && npm run lint && npm run webpack-build", "doc": "jsdoc -c build/jsdoc/jsdoc_conf.json -d docs/jsdoc", "test": "karma start test/unit/config/karma.unit.conf.cjs", - "test-functional": "karma start test/functional/config/karma.functional.conf.cjs --configfile=local/smoke", + "test-functional": "karma start test/functional/config/karma.functional.conf.cjs --configfile=local --streamsfile=smoke", "prepare": "node githook.cjs", "webpack-build": "rimraf dist && webpack --config build/webpack.prod.cjs" }, diff --git a/samples/dash-if-reference-player/app/contributors.json b/samples/dash-if-reference-player/app/contributors.json index 59c8c36d6e..67d7122853 100644 --- a/samples/dash-if-reference-player/app/contributors.json +++ b/samples/dash-if-reference-player/app/contributors.json @@ -63,6 +63,11 @@ "name": "Unified Streaming", "logo": "app/img/US-logo-petrol-rgb.jpg", "link": "https://www.unified-streaming.com/" + }, + { + "name": "Broadpeak", + "logo": "app/img/broadpeak.png", + "link": "https://broadpeak.tv/" } ] } diff --git a/samples/dash-if-reference-player/app/img/broadpeak.png b/samples/dash-if-reference-player/app/img/broadpeak.png new file mode 100644 index 0000000000000000000000000000000000000000..0287fade8acb623fb6329def91faa7a83e7d9ba9 GIT binary patch literal 58464 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 literal 0 HcmV?d00001 diff --git a/samples/dash-if-reference-player/app/sources.json b/samples/dash-if-reference-player/app/sources.json index 631abf51b2..486d24cd48 100644 --- a/samples/dash-if-reference-player/app/sources.json +++ b/samples/dash-if-reference-player/app/sources.json @@ -371,7 +371,7 @@ }, { "name": "TTML Sideloaded XML Subtitles", - "url": "https://livesim2.dashif.org/vod/testpic_2s/xml_subs.mpd", + "url": "https://livesim2.dashif.org/vod/testpic_2s/ttml_subs.mpd", "provider": "dashif" }, { diff --git a/test/functional/adapter/DashJsAdapter.js b/test/functional/adapter/DashJsAdapter.js index 60fa674a74..6b0b9e5c26 100644 --- a/test/functional/adapter/DashJsAdapter.js +++ b/test/functional/adapter/DashJsAdapter.js @@ -489,7 +489,7 @@ class DashJsAdapter { resolve(res); } const _onTimeout = () => { - _onComplete(null); + _onComplete({}); } const _onEvent = (e) => { if (e.request.type === 'MediaSegment') { diff --git a/test/functional/config/karma.functional.conf.cjs b/test/functional/config/karma.functional.conf.cjs index d792b7d468..38768351ca 100644 --- a/test/functional/config/karma.functional.conf.cjs +++ b/test/functional/config/karma.functional.conf.cjs @@ -7,16 +7,18 @@ module.exports = function (config) { const argv = yargs(hideBin(process.argv)).parse() // Find the settings JSON object in the command arguments const configFileName = argv.configfile + const streamsFileName = argv.streamsfile if (!configFileName) { return } - const testConfiguration = JSON.parse(fs.readFileSync(`test/functional/config/test-configurations/${configFileName}.json`, 'utf-8')) - const includedTestfiles = _getIncludedTestfiles(testConfiguration) - const excludedTestfiles = _getExcludedTestfiles(testConfiguration) + const testConfiguration = JSON.parse(fs.readFileSync(`test/functional/config/test-configurations/${configFileName}.json`, 'utf-8')); + const streamsConfiguration = JSON.parse(fs.readFileSync(`test/functional/config/test-configurations/streams/${streamsFileName}.json`, 'utf-8')); + const includedTestfiles = _getIncludedTestfiles(streamsConfiguration) + const excludedTestfiles = _getExcludedTestfiles(streamsConfiguration) const customContextFile = testConfiguration.customContextFile ? testConfiguration.customContextFile : 'test/functional/view/index.html'; - const testvectors = testConfiguration.testvectors + const testvectors = streamsConfiguration.testvectors config.set({ @@ -29,16 +31,8 @@ module.exports = function (config) { frameworks: ['mocha', 'chai', 'webpack'], plugins: [ - 'karma-webpack', - 'karma-mocha', - 'karma-chai', - 'karma-coverage', - 'karma-mocha-reporter', - 'karma-junit-reporter', - 'karma-chrome-launcher', - 'karma-firefox-launcher', - 'karma-htmlfile-reporter', - 'karma-browserstack-launcher' + 'karma-*', // default plugins + '@*/karma-*', // default scoped plugins ], // list of files / patterns to load in the browser @@ -59,7 +53,7 @@ module.exports = function (config) { // test results reporter to use // possible values: 'dots', 'progress' // available reporters: https://npmjs.org/browse/keyword/karma-reporter - reporters: ['mocha', 'html', 'progress', 'junit', 'coverage', 'BrowserStack'], + reporters: testConfiguration.reporters, // preprocess matching files before serving them to the browser // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor @@ -82,7 +76,7 @@ module.exports = function (config) { }, htmlReporter: { - outputFile: 'test/functional/results/test/karma/htmlreporter/out.html', + outputFile: `test/functional/results/test/karma/htmlreporter/${Date.now()}.html`, pageTitle: 'dash.js', subPageTitle: 'Functional Tests', groupSuites: true, @@ -152,11 +146,11 @@ module.exports = function (config) { 'os_version': '11', }, bs_safari_mac: { - 'base' : 'BrowserStack', - 'browser_version' : 'latest', - 'os' : 'OS X', - 'os_version' : 'Ventura', - 'browser' : 'safari', + 'base': 'BrowserStack', + 'browser_version': 'latest', + 'os': 'OS X', + 'os_version': 'Ventura', + 'browser': 'safari', }, chrome_custom: { base: 'Chrome', @@ -185,7 +179,7 @@ function _getIncludedTestfiles(testConfiguration) { } if (!testConfiguration.testfiles.included || testConfiguration.testfiles.included.indexOf('all') >= 0) { - return { pattern: `test/functional/test/**/*.js`, watched: false } + return [{ pattern: `test/functional/test/**/*.js`, watched: false }] } return testConfiguration.testfiles.included.map((entry) => { diff --git a/test/functional/config/test-configurations/browserstack.json b/test/functional/config/test-configurations/browserstack.json new file mode 100644 index 0000000000..b3c405e243 --- /dev/null +++ b/test/functional/config/test-configurations/browserstack.json @@ -0,0 +1,10 @@ +{ + "browsers": [ + "bs_chrome_win_11" + ], + "reporters": [ + "mocha", + "junit", + "BrowserStack" + ] +} diff --git a/test/functional/config/test-configurations/browserstack/drm_emsg_eptdelta_gaps.json b/test/functional/config/test-configurations/browserstack/drm_emsg_eptdelta_gaps.json deleted file mode 100644 index cbf455064b..0000000000 --- a/test/functional/config/test-configurations/browserstack/drm_emsg_eptdelta_gaps.json +++ /dev/null @@ -1,161 +0,0 @@ -{ - "browsers": [ - "bs_chrome_win_11" - ], - "testfiles": { - "included": [ - "all" - ], - "excluded": [ - "vendor/google-ad-manager-emsg" - ] - }, - "testvectors": [ - { - "name": "Segment Base", - "type": "vod", - "url": "https://dash.akamaized.net/dash264/TestCases/1a/sony/SNE_DASH_SD_CASE1A_REVISED.mpd" - }, - { - "name": "Segment Template, number based", - "type": "vod", - "url": "https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd" - }, - { - "name": "Segment Timeline, time based", - "type": "vod", - "url": "https://dash.akamaized.net/dash264/TestCases/2c/qualcomm/1/MultiResMPEG2.mpd" - }, - { - "name": "1080p with PlayReady and Widevine DRM, single key", - "type": "vod", - "url": "https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/Manifest_1080p.mpd", - "drm": { - "com.widevine.alpha": { - "serverURL": "https://drm-widevine-licensing.axtest.net/AcquireLicense", - "httpRequestHeaders": { - "X-AxDRM-Message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiYjMzNjRlYjUtNTFmNi00YWUzLThjOTgtMzNjZWQ1ZTMxYzc4IiwibWVzc2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIjoiOWViNDA1MGQtZTQ0Yi00ODAyLTkzMmUtMjdkNzUwODNlMjY2IiwiZW5jcnlwdGVkX2tleSI6ImxLM09qSExZVzI0Y3Iya3RSNzRmbnc9PSJ9XX19.4lWwW46k-oWcah8oN18LPj5OLS5ZU-_AQv7fe0JhNjA" - }, - "httpTimeout": 5000 - }, - "com.microsoft.playready": { - "serverURL": "https://drm-playready-licensing.axtest.net/AcquireLicense", - "httpRequestHeaders": { - "X-AxDRM-Message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiYjMzNjRlYjUtNTFmNi00YWUzLThjOTgtMzNjZWQ1ZTMxYzc4IiwibWVzc2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIjoiOWViNDA1MGQtZTQ0Yi00ODAyLTkzMmUtMjdkNzUwODNlMjY2IiwiZW5jcnlwdGVkX2tleSI6ImxLM09qSExZVzI0Y3Iya3RSNzRmbnc9PSJ9XX19.4lWwW46k-oWcah8oN18LPj5OLS5ZU-_AQv7fe0JhNjA" - }, - "httpTimeout": 5000 - } - } - }, - { - "name": "1080p with W3C Clear Key, single key", - "type": "vod", - "url": "https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/Manifest_1080p_ClearKey.mpd", - "drm": { - "org.w3.clearkey": { - "clearkeys": { - "nrQFDeRLSAKTLifXUIPiZg": "FmY0xnWCPCNaSpRG-tUuTQ" - } - } - } - }, - { - "name": "Shaka Demo Assets: Angel-One Widevine", - "type": "vod", - "url": "https://storage.googleapis.com/shaka-demo-assets/angel-one-widevine/dash.mpd", - "drm": { - "com.widevine.alpha": { - "serverURL": "https://cwip-shaka-proxy.appspot.com/no_auth" - } - } - }, - { - "name": "Livesim 2 ECCP with CBCS encryption and dashif:Laurl", - "type": "live", - "url": "https://livesim2.dashif.org/livesim2/eccp_cbcs/testpic_2s/Manifest.mpd" - }, - { - "name": "livesim2 SCTE35", - "type": "live", - "url": "https://livesim2.dashif.org/livesim2/scte35_2/testpic_2s/Manifest.mpd", - "includedTestfiles": [ - "feature-support/emsg-triggered" - ], - "testdata": { - "emsg": { - "minimumNumberOfEvents": 2, - "runtime": 65000, - "schemeIdUri": "urn:scte:scte35:2013:bin" - } - } - }, - { - "name": "Segment Timeline with negative video EPT Delta", - "type": "vod", - "url": "/base/test/functional/content/gap/video_negative_ept_delta.mpd", - "excludedTestfiles": [ - "playback/seek", - "payback-advanced/attach-at-non-zero" - ] - }, - { - "name": "Segment Timeline with negative audio EPT Delta", - "type": "vod", - "url": "/base/test/functional/content/gap/audio_negative_ept_delta.mpd", - "excludedTestfiles": [ - "playback/seek", - "payback-advanced/attach-at-non-zero" - ] - }, - { - "name": "Segment Timeline with positive video EPT Delta", - "type": "vod", - "url": "/base/test/functional/content/gap/video_negative_ept_delta.mpd", - "excludedTestfiles": [ - "playback/seek", - "payback-advanced/attach-at-non-zero" - ] - }, - { - "name": "Segment Timeline with positive audio EPT Delta", - "type": "vod", - "url": "/base/test/functional/content/gap/audio_negative_ept_delta.mpd", - "excludedTestfiles": [ - "playback/seek", - "payback-advanced/attach-at-non-zero" - ] - }, - { - "name": "Segment Timeline with missing audio segment in MPD for time 0", - "type": "vod", - "url": "/base/test/functional/content/gap/audio_gap_at_start_timeline.mpd", - "includedTestfiles": [ - "advanced/seek-in-gaps" - ], - "testdata": { - "gaps": [ - { - "start": 0, - "end": 5.97 - } - ] - } - }, - { - "name": "Segment Timeline with missing video segment in MPD for time 0", - "type": "vod", - "url": "/base/test/functional/content/gap/video_gap_at_start_timeline.mpd", - "includedTestfiles": [ - "advanced/seek-in-gaps" - ], - "testdata": { - "gaps": [ - { - "start": 0, - "end": 6 - } - ] - } - } - ] -} diff --git a/test/functional/config/test-configurations/browserstack/multiperiod_subtitle_vendor.json b/test/functional/config/test-configurations/browserstack/multiperiod_subtitle_vendor.json deleted file mode 100644 index 7a89d3f235..0000000000 --- a/test/functional/config/test-configurations/browserstack/multiperiod_subtitle_vendor.json +++ /dev/null @@ -1,240 +0,0 @@ -{ - "browsers": [ - "bs_chrome_win_11" - ], - "testfiles": { - "included": [ - "all" - ] - }, - "testvectors": [ - { - "name": "AWS Multiperiod unencrypted", - "type": "live", - "url": "https://d24rwxnt7vw9qb.cloudfront.net/v1/dash/e6d234965645b411ad572802b6c9d5a10799c9c1/All_Reference_Streams/4577dca5f8a44756875ab5cc913cd1f1/index.mpd", - "testdata": { - "periods": { - "waitingTimeForPeriodSwitches": 70000, - "minimumNumberOfPeriodSwitches": 1, - "maximumNumberOfPeriodSwitches": 15 - } - }, - "excludedTestfiles": [ - "advanced/no-reload-after-seek" - ] - }, - { - "name": "Multiperiod - Number + Timeline - Compact manifest - Thumbnails (1 track) - Encryption (2 keys : audio + video) - No key rotation", - "type": "live", - "url": "https://d24rwxnt7vw9qb.cloudfront.net/v1/dash/e6d234965645b411ad572802b6c9d5a10799c9c1/All_Reference_Streams//6e16c26536564c2f9dbc5f725a820cff/index.mpd", - "drm": { - "com.widevine.alpha": { - "serverURL": "https://lic.staging.drmtoday.com/license-proxy-widevine/cenc/?specConform=true", - "httpRequestHeaders": { - "x-dt-custom-data": "ewogICAgInVzZXJJZCI6ICJhd3MtZWxlbWVudGFsOjpzcGVrZS10ZXN0aW5nIiwKICAgICJzZXNzaW9uSWQiOiAiZWxlbWVudGFsLXJlZnN0cmVhbSIsCiAgICAibWVyY2hhbnQiOiAiYXdzLWVsZW1lbnRhbCIKfQo=" - } - }, - "com.microsoft.playready": { - "serverURL": "https://lic.staging.drmtoday.com/license-proxy-headerauth/drmtoday/RightsManager.asmx", - "httpRequestHeaders": { - "x-dt-custom-data": "ewogICAgInVzZXJJZCI6ICJhd3MtZWxlbWVudGFsOjpzcGVrZS10ZXN0aW5nIiwKICAgICJzZXNzaW9uSWQiOiAiZWxlbWVudGFsLXJlZnN0cmVhbSIsCiAgICAibWVyY2hhbnQiOiAiYXdzLWVsZW1lbnRhbCIKfQo=" - } - } - }, - "testdata": { - "periods": { - "waitingTimeForPeriodSwitches": 70000, - "minimumNumberOfPeriodSwitches": 1, - "maximumNumberOfPeriodSwitches": 15 - } - }, - "excludedTestfiles": [ - "advanced/no-reload-after-seek" - ] - }, - { - "name": "Multiperiod DASH-IF livesim2", - "type": "live", - "url": "https://livesim2.dashif.org/livesim2/periods_60/continuous_1/testpic_2s/Manifest.mpd", - "testdata": { - "periods": { - "waitingTimeForPeriodSwitches": 60000, - "minimumNumberOfPeriodSwitches": 1, - "maximumNumberOfPeriodSwitches": 2 - } - }, - "excludedTestfiles": [ - "advanced/no-reload-after-seek" - ] - }, - { - "url": "https://dash.akamaized.net/akamai/test/caption_test/ElephantsDream/elephants_dream_480p_heaac5_1_https.mpd", - "name": "External VTT subtitle file", - "provider": "dashif", - "type": "vod", - "includedTestfiles": [ - "text/switch-text" - ] - }, - { - "name": "TTML Segmented Subtitles VoD", - "url": "https://livesim2.dashif.org/dash/vod/testpic_2s/multi_subs.mpd", - "provider": "dashif", - "type": "vod", - "includedTestfiles": [ - "text/switch-text" - ] - }, - { - "name": "TTML Segmented Subtitles Live (livesim2)", - "url": "https://livesim2.dashif.org/livesim2/testpic_2s/multi_subs.mpd", - "provider": "dashif", - "type": "live", - "includedTestfiles": [ - "text/switch-text" - ] - }, - { - "name": "TTML Sideloaded XML Subtitles", - "url": "https://livesim2.dashif.org/dash/vod/testpic_2s/xml_subs.mpd", - "provider": "dashif", - "type": "vod", - "includedTestfiles": [ - "text/switch-text" - ] - }, - { - "name": "Embedded CEA-608 Closed Captions", - "url": "https://livesim2.dashif.org/dash/vod/testpic_2s/cea608.mpd", - "provider": "dashif", - "type": "vod", - "includedTestfiles": [ - "text/switch-text" - ] - }, - { - "name": "Embedded CEA-608 Closed Captions (livesim2)", - "url": "https://livesim2.dashif.org/livesim2/testpic_2s/cea608.mpd", - "provider": "dashif", - "type": "live", - "includedTestfiles": [ - "text/switch-text" - ] - }, - { - "name": "Embedded CEA-608 Closed Captions and TTML segments VoD", - "url": "https://livesim2.dashif.org/dash/vod/testpic_2s/cea608_and_segs.mpd", - "provider": "dashif", - "type": "vod", - "includedTestfiles": [ - "text/switch-text" - ] - }, - { - "name": "Embedded CEA-608 Closed Captions and TTML segments Live (livesim2)", - "url": "https://livesim2.dashif.org/livesim2/testpic_2s/cea608_and_segs.mpd", - "provider": "dashif", - "type": "live", - "includedTestfiles": [ - "text/switch-text" - ] - }, - { - "url": "https://livesim2.dashif.org/dash/vod/testpic_2s/imsc1_img.mpd", - "name": "IMSC1 (CMAF) Image Subtitles", - "moreInfo": "https://livesim2.dashif.org/dash/vod/testpic_2s/imsc1_img_subs_info.html", - "provider": "dashif", - "type": "vod", - "includedTestfiles": [ - "text/switch-text" - ] - }, - { - "name": "TTML Image Subtitles embedded (VoD)", - "url": "https://livesim2.dashif.org/dash/vod/testpic_2s/img_subs.mpd", - "moreInfo": "https://livesim2.dashif.org/dash/vod/testpic_2s/img_subs_info.html", - "provider": "dashif", - "type": "vod", - "includedTestfiles": [ - "text/switch-text" - ] - }, - { - "name": "TTML Segmented 'snaking' subtitles (with random text) (Ondemand)", - "url": "https://rdmedia.bbc.co.uk/elephants_dream/1/client_manifest-snake.mpd", - "moreInfo": "https://rdmedia.bbc.co.uk/elephants_dream/", - "provider": "bbc", - "type": "vod", - "includedTestfiles": [ - "text/switch-text" - ] - }, - { - "name": "BBC R&D EBU-TT-D Subtitling Test", - "url": "https://rdmedia.bbc.co.uk/elephants_dream/1/client_manifest-all.mpd", - "moreInfo": "https://rdmedia.bbc.co.uk/elephants_dream/", - "provider": "bbc", - "type": "vod", - "includedTestfiles": [ - "text/switch-text" - ] - }, - { - "name": "On-demand Testcard - WOFF Font Download signalled with supplemental property descriptor", - "url": "https://rdmedia.bbc.co.uk/testcard/vod/manifests/avc-ctv-stereo-en-sfdt-woff.mpd", - "moreInfo": "https://rdmedia.bbc.co.uk/testcard/vod/#feature-tests-font-downloads-for-subtitles", - "provider": "bbc", - "type": "live", - "includedTestfiles": [ - "text/switch-text" - ] - }, - { - "name": "On-demand Testcard - WOFF Font Download signalled with essential property descriptor", - "url": "https://rdmedia.bbc.co.uk/testcard/vod/manifests/avc-ctv-stereo-en-efdt-woff.mpd", - "moreInfo": "https://rdmedia.bbc.co.uk/testcard/vod/#feature-tests-font-downloads-for-subtitles", - "provider": "bbc", - "type": "live", - "includedTestfiles": [ - "text/switch-text" - ] - }, - { - "name": "Live Testcard - WOFF Font Download signalled with supplemental property descriptor", - "url": "https://rdmedia.bbc.co.uk/testcard/simulcast/manifests/avc-ctv-stereo-en-sfdt-woff.mpd", - "moreInfo": "https://rdmedia.bbc.co.uk/testcard/simulcast/#feature-tests-font-downloads-for-subtitles", - "provider": "bbc", - "type": "live", - "includedTestfiles": [ - "text/switch-text" - ] - }, - { - "name": "Live Testcard - WOFF Font Download signalled with essential property descriptor", - "url": "https://rdmedia.bbc.co.uk/testcard/simulcast/manifests/avc-ctv-stereo-en-efdt-woff.mpd", - "moreInfo": "https://rdmedia.bbc.co.uk/testcard/simulcast/#feature-tests-font-downloads-for-subtitles", - "provider": "bbc", - "type": "live", - "includedTestfiles": [ - "text/switch-text" - ] - }, - { - "url": "https://dash.akamaized.net/dash264/CTA/imsc1/IT1-20171027_dash.mpd", - "name": "IMSC1 Text Subtitles via sidecar file", - "provider": "cta", - "type": "vod", - "includedTestfiles": [ - "text/switch-text" - ] - }, - { - "url": "https://storage.googleapis.com/shaka-demo-assets/sintel-many-subs/dash.mpd", - "name": "Shaka 44 different subtitles", - "type": "vod", - "includedTestfiles": [ - "text/switch-text" - ] - } - ] -} diff --git a/test/functional/config/test-configurations/browserstack/single.json b/test/functional/config/test-configurations/browserstack/single.json deleted file mode 100644 index 9a4caea819..0000000000 --- a/test/functional/config/test-configurations/browserstack/single.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "browsers": [ - "bs_chrome_win_11", - "bs_firefox_win_11", - "bs_safari_mac" - ], - "testfiles": { - "included": [ - "all" - ], - "excluded": [ - "vendor/google-ad-manager-emsg" - ] - }, - "testvectors": [ - { - "name": "DASH-IF Live Sim - Segment Template without manifest updates", - "type": "live", - "url": "https://livesim2.dashif.org/livesim2/testpic_2s/Manifest.mpd", - "includedTestfiles": [ - "playback/play", - "playback/pause", - "playback/seek" - ] - } - ] -} diff --git a/test/functional/config/test-configurations/browserstack/smoke.json b/test/functional/config/test-configurations/browserstack/smoke.json deleted file mode 100644 index 178bcd1538..0000000000 --- a/test/functional/config/test-configurations/browserstack/smoke.json +++ /dev/null @@ -1,167 +0,0 @@ -{ - "browsers": [ - "bs_chrome_win_11" - ], - "testfiles": { - "included": [ - "all" - ], - "excluded": [ - "vendor/google-ad-manager-emsg" - ] - }, - "testvectors": [ - { - "name": "1080p with PlayReady and Widevine DRM, single key", - "type": "vod", - "url": "https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/Manifest_1080p.mpd", - "drm": { - "com.widevine.alpha": { - "serverURL": "https://drm-widevine-licensing.axtest.net/AcquireLicense", - "httpRequestHeaders": { - "X-AxDRM-Message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiYjMzNjRlYjUtNTFmNi00YWUzLThjOTgtMzNjZWQ1ZTMxYzc4IiwibWVzc2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIjoiOWViNDA1MGQtZTQ0Yi00ODAyLTkzMmUtMjdkNzUwODNlMjY2IiwiZW5jcnlwdGVkX2tleSI6ImxLM09qSExZVzI0Y3Iya3RSNzRmbnc9PSJ9XX19.4lWwW46k-oWcah8oN18LPj5OLS5ZU-_AQv7fe0JhNjA" - }, - "httpTimeout": 5000 - }, - "com.microsoft.playready": { - "serverURL": "https://drm-playready-licensing.axtest.net/AcquireLicense", - "httpRequestHeaders": { - "X-AxDRM-Message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiYjMzNjRlYjUtNTFmNi00YWUzLThjOTgtMzNjZWQ1ZTMxYzc4IiwibWVzc2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIjoiOWViNDA1MGQtZTQ0Yi00ODAyLTkzMmUtMjdkNzUwODNlMjY2IiwiZW5jcnlwdGVkX2tleSI6ImxLM09qSExZVzI0Y3Iya3RSNzRmbnc9PSJ9XX19.4lWwW46k-oWcah8oN18LPj5OLS5ZU-_AQv7fe0JhNjA" - }, - "httpTimeout": 5000 - } - }, - "includedTestfiles": [ - "playback/play", - "playback/pause", - "playback/seek", - "audio/*", - "text/*" - ] - }, - { - "name": "1080p with W3C Clear Key, single key", - "type": "vod", - "url": "https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/Manifest_1080p_ClearKey.mpd", - "drm": { - "org.w3.clearkey": { - "clearkeys": { - "nrQFDeRLSAKTLifXUIPiZg": "FmY0xnWCPCNaSpRG-tUuTQ" - } - } - }, - "includedTestfiles": [ - "playback/play", - "playback/pause", - "playback/seek" - ] - }, - { - "name": "livesim2 SCTE35", - "type": "live", - "url": "https://livesim2.dashif.org/livesim2/scte35_2/testpic_2s/Manifest.mpd", - "includedTestfiles": [ - "feature-support/emsg-triggered" - ], - "testdata": { - "emsg": { - "minimumNumberOfEvents": 2, - "runtime": 65000, - "schemeIdUri": "urn:scte:scte35:2013:bin" - } - } - }, - { - "name": "DASH-IF Live Sim - Segment Template without manifest updates", - "type": "live", - "url": "https://livesim2.dashif.org/livesim2/testpic_2s/Manifest.mpd", - "includedTestfiles": [ - "playback/play", - "playback/pause", - "playback/seek", - "playback-advanced/cmcd", - "playback-advanced/preload" - ] - }, - { - "name": "Segment Timeline with $time$", - "url": "https://livesim2.dashif.org/livesim2/segtimeline_1/testpic_2s/Manifest.mpd", - "type": "live", - "includedTestfiles": [ - "playback/play", - "playback/pause", - "playback/seek" - ] - }, - { - "name": "Segment Timeline with $number$", - "url": "https://livesim2.dashif.org/livesim2/segtimelinenr_1/testpic_2s/Manifest.mpd", - "type": "live", - "includedTestfiles": [ - "playback/play", - "playback/pause", - "playback/seek" - ] - }, - { - "name": "Audio only live", - "url": "https://livesim2.dashif.org/livesim2/testpic_2s/audio.mpd", - "type": "live", - "includedTestfiles": [ - "playback/play", - "playback/pause", - "playback/seek" - ] - }, - { - "name": "MSS", - "type": "vod", - "url": "https://playready.directtaps.net/smoothstreaming/SSWSS720H264/SuperSpeedway_720.ism/Manifest", - "includedTestfiles": [ - "playback/play", - "playback/pause", - "playback/seek" - ] - }, - { - "name": "AWS Multiperiod unencrypted", - "type": "live", - "url": "https://d24rwxnt7vw9qb.cloudfront.net/v1/dash/e6d234965645b411ad572802b6c9d5a10799c9c1/All_Reference_Streams/4577dca5f8a44756875ab5cc913cd1f1/index.mpd", - "testdata": { - "periods": { - "waitingTimeForPeriodSwitches": 70000, - "minimumNumberOfPeriodSwitches": 1, - "maximumNumberOfPeriodSwitches": 15 - } - }, - "includedTestfiles": [ - "playback/play", - "playback/pause", - "playback/seek", - "playback-advanced/multiperiod-playback" - ] - }, - { - "name": "TTML Segmented Subtitles Live (livesim2)", - "url": "https://livesim2.dashif.org/livesim2/testpic_2s/multi_subs.mpd", - "provider": "dashif", - "type": "live", - "includedTestfiles": [ - "playback/play", - "playback/pause", - "playback/seek", - "text/*" - ] - }, - { - "name": "Segment Base", - "type": "vod", - "url": "https://dash.akamaized.net/dash264/TestCases/1a/sony/SNE_DASH_SD_CASE1A_REVISED.mpd", - "includedTestfiles": [ - "playback/play", - "playback/pause", - "playback/seek" - ] - } - ] -} diff --git a/test/functional/config/test-configurations/browserstack/vod_live_lowlatency_mss_multiaudio.json b/test/functional/config/test-configurations/browserstack/vod_live_lowlatency_mss_multiaudio.json deleted file mode 100644 index 0a5f4c8f19..0000000000 --- a/test/functional/config/test-configurations/browserstack/vod_live_lowlatency_mss_multiaudio.json +++ /dev/null @@ -1,65 +0,0 @@ -{ - "browsers": [ - "bs_chrome_win_11" - ], - "testfiles": { - "included": [ - "all" - ], - "excluded": [ - "vendor/google-ad-manager-emsg" - ] - }, - "testvectors": [ - { - "name": "DASH-IF Live Sim - Segment Template without manifest updates", - "type": "live", - "url": "https://livesim2.dashif.org/livesim2/testpic_2s/Manifest.mpd" - }, - { - "name": "Segment Timeline with $time$", - "url": "https://livesim2.dashif.org/livesim2/segtimeline_1/testpic_2s/Manifest.mpd", - "type": "live" - }, - { - "name": "Segment Timeline with $number$", - "url": "https://livesim2.dashif.org/livesim2/segtimelinenr_1/testpic_2s/Manifest.mpd", - "type": "live" - }, - { - "name": "AWS Single Period $number$", - "url": "https://d10gktn8v7end7.cloudfront.net/out/v1/6ee19df3afa24fe190a8ae16c2c88560/index.mpd", - "type": "live" - }, - { - "name": "Audio only live", - "url": "https://livesim2.dashif.org/livesim2/testpic_2s/audio.mpd", - "type": "live" - }, - { - "name": "Akamai Low Latency - Multi Rate", - "type": "live", - "url": "https://cmafref.akamaized.net/cmaf/live-ull/2006350/akambr/out.mpd" - }, - { - "name": "MSS", - "type": "vod", - "url": "https://playready.directtaps.net/smoothstreaming/SSWSS720H264/SuperSpeedway_720.ism/Manifest" - }, - { - "name": "Multi audio", - "type": "vod", - "url": "http://refapp.hbbtv.org/videos/02_gran_dillama_1080p_ma_25f75g6sv5/manifest.mpd" - }, - { - "name": "Shaka Demo Assets: Angel-One Widevine", - "type": "vod", - "url": "https://storage.googleapis.com/shaka-demo-assets/angel-one-widevine/dash.mpd", - "drm": { - "com.widevine.alpha": { - "serverURL": "https://cwip-shaka-proxy.appspot.com/no_auth" - } - } - } - ] -} diff --git a/test/functional/config/test-configurations/local.json b/test/functional/config/test-configurations/local.json new file mode 100644 index 0000000000..f9821f7380 --- /dev/null +++ b/test/functional/config/test-configurations/local.json @@ -0,0 +1,11 @@ +{ + "browsers": [ + "chrome_custom", + "firefox_custom" + ], + "reporters": [ + "mocha", + "html", + "coverage" + ] +} diff --git a/test/functional/config/test-configurations/local/single.json b/test/functional/config/test-configurations/local/single.json deleted file mode 100644 index 705920c0ed..0000000000 --- a/test/functional/config/test-configurations/local/single.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "browsers": [ - "chrome_custom" - ], - "testfiles": { - "included": [ - "all" - ], - "excluded": [ - "vendor/google-ad-manager-emsg" - ] - }, - "testvectors": [ - { - "name": "1080p with PlayReady and Widevine DRM, single key", - "type": "vod", - "url": "https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/Manifest_1080p.mpd", - "drm": { - "com.widevine.alpha": { - "serverURL": "https://drm-widevine-licensing.axtest.net/AcquireLicense", - "httpRequestHeaders": { - "X-AxDRM-Message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiYjMzNjRlYjUtNTFmNi00YWUzLThjOTgtMzNjZWQ1ZTMxYzc4IiwibWVzc2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIjoiOWViNDA1MGQtZTQ0Yi00ODAyLTkzMmUtMjdkNzUwODNlMjY2IiwiZW5jcnlwdGVkX2tleSI6ImxLM09qSExZVzI0Y3Iya3RSNzRmbnc9PSJ9XX19.4lWwW46k-oWcah8oN18LPj5OLS5ZU-_AQv7fe0JhNjA" - }, - "httpTimeout": 5000 - }, - "com.microsoft.playready": { - "serverURL": "https://drm-playready-licensing.axtest.net/AcquireLicense", - "httpRequestHeaders": { - "X-AxDRM-Message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiYjMzNjRlYjUtNTFmNi00YWUzLThjOTgtMzNjZWQ1ZTMxYzc4IiwibWVzc2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIjoiOWViNDA1MGQtZTQ0Yi00ODAyLTkzMmUtMjdkNzUwODNlMjY2IiwiZW5jcnlwdGVkX2tleSI6ImxLM09qSExZVzI0Y3Iya3RSNzRmbnc9PSJ9XX19.4lWwW46k-oWcah8oN18LPj5OLS5ZU-_AQv7fe0JhNjA" - }, - "httpTimeout": 5000 - } - }, - "includedTestfiles": [ - "text/*" - ] - } - ] -} diff --git a/test/functional/config/test-configurations/local/all.json b/test/functional/config/test-configurations/streams/all.json similarity index 71% rename from test/functional/config/test-configurations/local/all.json rename to test/functional/config/test-configurations/streams/all.json index 3748dc846b..d8eff6677d 100644 --- a/test/functional/config/test-configurations/local/all.json +++ b/test/functional/config/test-configurations/streams/all.json @@ -1,8 +1,4 @@ { - "browsers": [ - "chrome_custom", - "firefox_custom" - ], "testfiles": { "included": [ "all" @@ -13,198 +9,44 @@ }, "testvectors": [ { - "name": "Segment Base", - "type": "vod", - "url": "https://dash.akamaized.net/dash264/TestCases/1a/sony/SNE_DASH_SD_CASE1A_REVISED.mpd" - }, - { - "name": "Segment Template, number based", - "type": "vod", - "url": "https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd" - }, - { - "name": "Segment Timeline, time based", - "type": "vod", - "url": "https://dash.akamaized.net/dash264/TestCases/2c/qualcomm/1/MultiResMPEG2.mpd" - }, - { - "name": "1080p with PlayReady and Widevine DRM, single key", - "type": "vod", - "url": "https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/Manifest_1080p.mpd", - "drm": { - "com.widevine.alpha": { - "serverURL": "https://drm-widevine-licensing.axtest.net/AcquireLicense", - "httpRequestHeaders": { - "X-AxDRM-Message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiYjMzNjRlYjUtNTFmNi00YWUzLThjOTgtMzNjZWQ1ZTMxYzc4IiwibWVzc2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIjoiOWViNDA1MGQtZTQ0Yi00ODAyLTkzMmUtMjdkNzUwODNlMjY2IiwiZW5jcnlwdGVkX2tleSI6ImxLM09qSExZVzI0Y3Iya3RSNzRmbnc9PSJ9XX19.4lWwW46k-oWcah8oN18LPj5OLS5ZU-_AQv7fe0JhNjA" - }, - "httpTimeout": 5000 - }, - "com.microsoft.playready": { - "serverURL": "https://drm-playready-licensing.axtest.net/AcquireLicense", - "httpRequestHeaders": { - "X-AxDRM-Message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiYjMzNjRlYjUtNTFmNi00YWUzLThjOTgtMzNjZWQ1ZTMxYzc4IiwibWVzc2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIjoiOWViNDA1MGQtZTQ0Yi00ODAyLTkzMmUtMjdkNzUwODNlMjY2IiwiZW5jcnlwdGVkX2tleSI6ImxLM09qSExZVzI0Y3Iya3RSNzRmbnc9PSJ9XX19.4lWwW46k-oWcah8oN18LPj5OLS5ZU-_AQv7fe0JhNjA" - }, - "httpTimeout": 5000 - } - } - }, - { - "name": "1080p with W3C Clear Key, single key", - "type": "vod", - "url": "https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/Manifest_1080p_ClearKey.mpd", - "drm": { - "org.w3.clearkey": { - "clearkeys": { - "nrQFDeRLSAKTLifXUIPiZg": "FmY0xnWCPCNaSpRG-tUuTQ" - } - } - } - }, - { - "name": "Shaka Demo Assets: Angel-One Widevine", - "type": "vod", - "url": "https://storage.googleapis.com/shaka-demo-assets/angel-one-widevine/dash.mpd", - "drm": { - "com.widevine.alpha": { - "serverURL": "https://cwip-shaka-proxy.appspot.com/no_auth" - } - } - }, - { - "name": "Livesim 2 ECCP with CBCS encryption and dashif:Laurl", - "type": "live", - "url": "https://livesim2.dashif.org/livesim2/eccp_cbcs/testpic_2s/Manifest.mpd" - }, - { - "name": "livesim2 SCTE35", + "name": "DASH-IF Live Sim - Segment Template without manifest updates", "type": "live", - "url": "https://livesim2.dashif.org/livesim2/scte35_2/testpic_2s/Manifest.mpd", - "includedTestfiles": [ - "feature-support/emsg-triggered" - ], - "testdata": { - "emsg": { - "minimumNumberOfEvents": 2, - "runtime": 65000, - "schemeIdUri": "urn:scte:scte35:2013:bin" - } - } + "url": "https://livesim2.dashif.org/livesim2/testpic_2s/Manifest.mpd" }, { - "name": "Segment Timeline with negative video EPT Delta", - "type": "vod", - "url": "/base/test/functional/content/gap/video_negative_ept_delta.mpd", - "excludedTestfiles": [ - "playback/seek", - "payback-advanced/attach-at-non-zero" - ] + "name": "Segment Timeline with $time$", + "url": "https://livesim2.dashif.org/livesim2/segtimeline_1/testpic_2s/Manifest.mpd", + "type": "live" }, { - "name": "Segment Timeline with negative audio EPT Delta", - "type": "vod", - "url": "/base/test/functional/content/gap/audio_negative_ept_delta.mpd", - "excludedTestfiles": [ - "playback/seek", - "payback-advanced/attach-at-non-zero" - ] + "name": "Segment Timeline with $number$", + "url": "https://livesim2.dashif.org/livesim2/segtimelinenr_1/testpic_2s/Manifest.mpd", + "type": "live" }, { - "name": "Segment Timeline with positive video EPT Delta", - "type": "vod", - "url": "/base/test/functional/content/gap/video_negative_ept_delta.mpd", - "excludedTestfiles": [ - "playback/seek", - "payback-advanced/attach-at-non-zero" - ] + "name": "AWS Single Period $number$", + "url": "https://d10gktn8v7end7.cloudfront.net/out/v1/6ee19df3afa24fe190a8ae16c2c88560/index.mpd", + "type": "live" }, { - "name": "Segment Timeline with positive audio EPT Delta", - "type": "vod", - "url": "/base/test/functional/content/gap/audio_negative_ept_delta.mpd", - "excludedTestfiles": [ - "playback/seek", - "payback-advanced/attach-at-non-zero" - ] + "name": "Audio only live", + "url": "https://livesim2.dashif.org/livesim2/testpic_2s/audio.mpd", + "type": "live" }, { - "name": "Segment Timeline with missing audio segment in MPD for time 0", - "type": "vod", - "url": "/base/test/functional/content/gap/audio_gap_at_start_timeline.mpd", - "includedTestfiles": [ - "advanced/seek-in-gaps" - ], - "testdata": { - "gaps": [ - { - "start": 0, - "end": 5.97 - } - ] - } - }, - { - "name": "Segment Timeline with missing video segment in MPD for time 0", - "type": "vod", - "url": "/base/test/functional/content/gap/video_gap_at_start_timeline.mpd", - "includedTestfiles": [ - "advanced/seek-in-gaps" - ], - "testdata": { - "gaps": [ - { - "start": 0, - "end": 6 - } - ] - } - }, - { - "name": "Segment Base", - "type": "vod", - "url": "https://dash.akamaized.net/dash264/TestCases/1a/sony/SNE_DASH_SD_CASE1A_REVISED.mpd" + "name": "Akamai Low Latency - Multi Rate", + "type": "live", + "url": "https://cmafref.akamaized.net/cmaf/live-ull/2006350/akambr/out.mpd" }, { - "name": "Segment Template, number based", + "name": "MSS", "type": "vod", - "url": "https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd" + "url": "https://playready.directtaps.net/smoothstreaming/SSWSS720H264/SuperSpeedway_720.ism/Manifest" }, { - "name": "Segment Timeline, time based", + "name": "Multi audio", "type": "vod", - "url": "https://dash.akamaized.net/dash264/TestCases/2c/qualcomm/1/MultiResMPEG2.mpd" - }, - { - "name": "1080p with PlayReady and Widevine DRM, single key", - "type": "vod", - "url": "https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/Manifest_1080p.mpd", - "drm": { - "com.widevine.alpha": { - "serverURL": "https://drm-widevine-licensing.axtest.net/AcquireLicense", - "httpRequestHeaders": { - "X-AxDRM-Message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiYjMzNjRlYjUtNTFmNi00YWUzLThjOTgtMzNjZWQ1ZTMxYzc4IiwibWVzc2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIjoiOWViNDA1MGQtZTQ0Yi00ODAyLTkzMmUtMjdkNzUwODNlMjY2IiwiZW5jcnlwdGVkX2tleSI6ImxLM09qSExZVzI0Y3Iya3RSNzRmbnc9PSJ9XX19.4lWwW46k-oWcah8oN18LPj5OLS5ZU-_AQv7fe0JhNjA" - }, - "httpTimeout": 5000 - }, - "com.microsoft.playready": { - "serverURL": "https://drm-playready-licensing.axtest.net/AcquireLicense", - "httpRequestHeaders": { - "X-AxDRM-Message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiYjMzNjRlYjUtNTFmNi00YWUzLThjOTgtMzNjZWQ1ZTMxYzc4IiwibWVzc2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIjoiOWViNDA1MGQtZTQ0Yi00ODAyLTkzMmUtMjdkNzUwODNlMjY2IiwiZW5jcnlwdGVkX2tleSI6ImxLM09qSExZVzI0Y3Iya3RSNzRmbnc9PSJ9XX19.4lWwW46k-oWcah8oN18LPj5OLS5ZU-_AQv7fe0JhNjA" - }, - "httpTimeout": 5000 - } - } - }, - { - "name": "1080p with W3C Clear Key, single key", - "type": "vod", - "url": "https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/Manifest_1080p_ClearKey.mpd", - "drm": { - "org.w3.clearkey": { - "clearkeys": { - "nrQFDeRLSAKTLifXUIPiZg": "FmY0xnWCPCNaSpRG-tUuTQ" - } - } - } + "url": "http://refapp.hbbtv.org/videos/02_gran_dillama_1080p_ma_25f75g6sv5/manifest.mpd" }, { "name": "Shaka Demo Assets: Angel-One Widevine", @@ -216,94 +58,6 @@ } } }, - { - "name": "Livesim 2 ECCP with CBCS encryption and dashif:Laurl", - "type": "live", - "url": "https://livesim2.dashif.org/livesim2/eccp_cbcs/testpic_2s/Manifest.mpd" - }, - { - "name": "livesim2 SCTE35", - "type": "live", - "url": "https://livesim2.dashif.org/livesim2/scte35_2/testpic_2s/Manifest.mpd", - "includedTestfiles": [ - "feature-support/emsg-triggered" - ], - "testdata": { - "emsg": { - "minimumNumberOfEvents": 2, - "runtime": 65000, - "schemeIdUri": "urn:scte:scte35:2013:bin" - } - } - }, - { - "name": "Segment Timeline with negative video EPT Delta", - "type": "vod", - "url": "/base/test/functional/content/gap/video_negative_ept_delta.mpd", - "excludedTestfiles": [ - "playback/seek", - "payback-advanced/attach-at-non-zero" - ] - }, - { - "name": "Segment Timeline with negative audio EPT Delta", - "type": "vod", - "url": "/base/test/functional/content/gap/audio_negative_ept_delta.mpd", - "excludedTestfiles": [ - "playback/seek", - "payback-advanced/attach-at-non-zero" - ] - }, - { - "name": "Segment Timeline with positive video EPT Delta", - "type": "vod", - "url": "/base/test/functional/content/gap/video_negative_ept_delta.mpd", - "excludedTestfiles": [ - "playback/seek", - "payback-advanced/attach-at-non-zero" - ] - }, - { - "name": "Segment Timeline with positive audio EPT Delta", - "type": "vod", - "url": "/base/test/functional/content/gap/audio_negative_ept_delta.mpd", - "excludedTestfiles": [ - "playback/seek", - "payback-advanced/attach-at-non-zero" - ] - }, - { - "name": "Segment Timeline with missing audio segment in MPD for time 0", - "type": "vod", - "url": "/base/test/functional/content/gap/audio_gap_at_start_timeline.mpd", - "includedTestfiles": [ - "advanced/seek-in-gaps" - ], - "testdata": { - "gaps": [ - { - "start": 0, - "end": 5.97 - } - ] - } - }, - { - "name": "Segment Timeline with missing video segment in MPD for time 0", - "type": "vod", - "url": "/base/test/functional/content/gap/video_gap_at_start_timeline.mpd", - "includedTestfiles": [ - "advanced/seek-in-gaps" - ], - "testdata": { - "gaps": [ - { - "start": 0, - "end": 6 - } - ] - } - }, { "name": "AWS Multiperiod unencrypted", "type": "live", @@ -392,7 +146,7 @@ }, { "name": "TTML Sideloaded XML Subtitles", - "url": "https://livesim2.dashif.org/dash/vod/testpic_2s/xml_subs.mpd", + "url": "https://livesim2.dashif.org/vod/testpic_2s/ttml_subs.mpd", "provider": "dashif", "type": "vod", "includedTestfiles": [ @@ -531,6 +285,140 @@ "includedTestfiles": [ "text/*" ] + }, + { + "name": "1080p with PlayReady and Widevine DRM, single key", + "type": "vod", + "url": "https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/Manifest_1080p.mpd", + "drm": { + "com.widevine.alpha": { + "serverURL": "https://drm-widevine-licensing.axtest.net/AcquireLicense", + "httpRequestHeaders": { + "X-AxDRM-Message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiYjMzNjRlYjUtNTFmNi00YWUzLThjOTgtMzNjZWQ1ZTMxYzc4IiwibWVzc2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIjoiOWViNDA1MGQtZTQ0Yi00ODAyLTkzMmUtMjdkNzUwODNlMjY2IiwiZW5jcnlwdGVkX2tleSI6ImxLM09qSExZVzI0Y3Iya3RSNzRmbnc9PSJ9XX19.4lWwW46k-oWcah8oN18LPj5OLS5ZU-_AQv7fe0JhNjA" + }, + "httpTimeout": 5000 + }, + "com.microsoft.playready": { + "serverURL": "https://drm-playready-licensing.axtest.net/AcquireLicense", + "httpRequestHeaders": { + "X-AxDRM-Message": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ2ZXJzaW9uIjoxLCJjb21fa2V5X2lkIjoiYjMzNjRlYjUtNTFmNi00YWUzLThjOTgtMzNjZWQ1ZTMxYzc4IiwibWVzc2FnZSI6eyJ0eXBlIjoiZW50aXRsZW1lbnRfbWVzc2FnZSIsImtleXMiOlt7ImlkIjoiOWViNDA1MGQtZTQ0Yi00ODAyLTkzMmUtMjdkNzUwODNlMjY2IiwiZW5jcnlwdGVkX2tleSI6ImxLM09qSExZVzI0Y3Iya3RSNzRmbnc9PSJ9XX19.4lWwW46k-oWcah8oN18LPj5OLS5ZU-_AQv7fe0JhNjA" + }, + "httpTimeout": 5000 + } + } + }, + { + "name": "1080p with W3C Clear Key, single key", + "type": "vod", + "url": "https://media.axprod.net/TestVectors/v7-MultiDRM-SingleKey/Manifest_1080p_ClearKey.mpd", + "drm": { + "org.w3.clearkey": { + "clearkeys": { + "nrQFDeRLSAKTLifXUIPiZg": "FmY0xnWCPCNaSpRG-tUuTQ" + } + } + } + }, + { + "name": "Shaka Demo Assets: Angel-One Widevine", + "type": "vod", + "url": "https://storage.googleapis.com/shaka-demo-assets/angel-one-widevine/dash.mpd", + "drm": { + "com.widevine.alpha": { + "serverURL": "https://cwip-shaka-proxy.appspot.com/no_auth" + } + } + }, + { + "name": "Livesim 2 ECCP with CBCS encryption and dashif:Laurl", + "type": "live", + "url": "https://livesim2.dashif.org/livesim2/eccp_cbcs/testpic_2s/Manifest.mpd", + "excludedTestfiles": [ + "playback-advanced/preload" + ] + }, + { + "name": "livesim2 SCTE35", + "type": "live", + "url": "https://livesim2.dashif.org/livesim2/scte35_2/testpic_2s/Manifest.mpd", + "includedTestfiles": [ + "feature-support/emsg-triggered" + ], + "testdata": { + "emsg": { + "minimumNumberOfEvents": 2, + "runtime": 65000, + "schemeIdUri": "urn:scte:scte35:2013:bin" + } + } + }, + { + "name": "Segment Timeline with negative video EPT Delta", + "type": "vod", + "url": "/base/test/functional/content/gap/video_negative_ept_delta.mpd", + "excludedTestfiles": [ + "playback/seek", + "payback-advanced/attach-at-non-zero" + ] + }, + { + "name": "Segment Timeline with negative audio EPT Delta", + "type": "vod", + "url": "/base/test/functional/content/gap/audio_negative_ept_delta.mpd", + "excludedTestfiles": [ + "playback/seek", + "payback-advanced/attach-at-non-zero" + ] + }, + { + "name": "Segment Timeline with positive video EPT Delta", + "type": "vod", + "url": "/base/test/functional/content/gap/video_negative_ept_delta.mpd", + "excludedTestfiles": [ + "playback/seek", + "payback-advanced/attach-at-non-zero" + ] + }, + { + "name": "Segment Timeline with positive audio EPT Delta", + "type": "vod", + "url": "/base/test/functional/content/gap/audio_negative_ept_delta.mpd", + "excludedTestfiles": [ + "playback/seek", + "payback-advanced/attach-at-non-zero" + ] + }, + { + "name": "Segment Timeline with missing audio segment in MPD for time 0", + "type": "vod", + "url": "/base/test/functional/content/gap/audio_gap_at_start_timeline.mpd", + "includedTestfiles": [ + "advanced/seek-in-gaps" + ], + "testdata": { + "gaps": [ + { + "start": 0, + "end": 5.97 + } + ] + } + }, + { + "name": "Segment Timeline with missing video segment in MPD for time 0", + "type": "vod", + "url": "/base/test/functional/content/gap/video_gap_at_start_timeline.mpd", + "includedTestfiles": [ + "advanced/seek-in-gaps" + ], + "testdata": { + "gaps": [ + { + "start": 0, + "end": 6 + } + ] + } } ] } diff --git a/test/functional/config/test-configurations/local/drm_emsg_eptdelta_gaps.json b/test/functional/config/test-configurations/streams/drm_emsg_eptdelta_gaps.json similarity index 89% rename from test/functional/config/test-configurations/local/drm_emsg_eptdelta_gaps.json rename to test/functional/config/test-configurations/streams/drm_emsg_eptdelta_gaps.json index 0898983cb7..b9df29db8d 100644 --- a/test/functional/config/test-configurations/local/drm_emsg_eptdelta_gaps.json +++ b/test/functional/config/test-configurations/streams/drm_emsg_eptdelta_gaps.json @@ -1,7 +1,4 @@ { - "browsers": [ - "chrome_custom" - ], "testfiles": { "included": [ "all" @@ -11,21 +8,6 @@ ] }, "testvectors": [ - { - "name": "Segment Base", - "type": "vod", - "url": "https://dash.akamaized.net/dash264/TestCases/1a/sony/SNE_DASH_SD_CASE1A_REVISED.mpd" - }, - { - "name": "Segment Template, number based", - "type": "vod", - "url": "https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd" - }, - { - "name": "Segment Timeline, time based", - "type": "vod", - "url": "https://dash.akamaized.net/dash264/TestCases/2c/qualcomm/1/MultiResMPEG2.mpd" - }, { "name": "1080p with PlayReady and Widevine DRM, single key", "type": "vod", @@ -72,7 +54,8 @@ { "name": "Livesim 2 ECCP with CBCS encryption and dashif:Laurl", "type": "live", - "url": "https://livesim2.dashif.org/livesim2/eccp_cbcs/testpic_2s/Manifest.mpd" + "url": "https://livesim2.dashif.org/livesim2/eccp_cbcs/testpic_2s/Manifest.mpd", + "excludedTestfiles": ["playback-advanced/preload"] }, { "name": "livesim2 SCTE35", diff --git a/test/functional/config/test-configurations/local/multiperiod_subtitle_vendor.json b/test/functional/config/test-configurations/streams/multiperiod_subtitle_vendor.json similarity index 92% rename from test/functional/config/test-configurations/local/multiperiod_subtitle_vendor.json rename to test/functional/config/test-configurations/streams/multiperiod_subtitle_vendor.json index 70a99501be..feabd67ec0 100644 --- a/test/functional/config/test-configurations/local/multiperiod_subtitle_vendor.json +++ b/test/functional/config/test-configurations/streams/multiperiod_subtitle_vendor.json @@ -1,7 +1,4 @@ { - "browsers": [ - "chrome_custom" - ], "testfiles": { "included": [ "all" @@ -73,7 +70,7 @@ "provider": "dashif", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -82,7 +79,7 @@ "provider": "dashif", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -91,16 +88,16 @@ "provider": "dashif", "type": "live", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { "name": "TTML Sideloaded XML Subtitles", - "url": "https://livesim2.dashif.org/dash/vod/testpic_2s/xml_subs.mpd", + "url": "https://livesim2.dashif.org/vod/testpic_2s/ttml_subs.mpd", "provider": "dashif", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -109,7 +106,7 @@ "provider": "dashif", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -118,7 +115,7 @@ "provider": "dashif", "type": "live", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -127,7 +124,7 @@ "provider": "dashif", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -136,7 +133,7 @@ "provider": "dashif", "type": "live", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -146,7 +143,7 @@ "provider": "dashif", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -156,7 +153,7 @@ "provider": "dashif", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -166,7 +163,7 @@ "provider": "bbc", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -176,7 +173,7 @@ "provider": "bbc", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -186,7 +183,7 @@ "provider": "bbc", "type": "live", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -196,7 +193,7 @@ "provider": "bbc", "type": "live", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -206,7 +203,7 @@ "provider": "bbc", "type": "live", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -216,7 +213,7 @@ "provider": "bbc", "type": "live", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -225,7 +222,7 @@ "provider": "cta", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -233,7 +230,7 @@ "name": "Shaka 44 different subtitles", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] } ] diff --git a/test/functional/config/test-configurations/streams/single.json b/test/functional/config/test-configurations/streams/single.json new file mode 100644 index 0000000000..462f24d6fa --- /dev/null +++ b/test/functional/config/test-configurations/streams/single.json @@ -0,0 +1,20 @@ +{ + "testfiles": { + "included": [ + "all" + ], + "excluded": [ + "vendor/google-ad-manager-emsg" + ] + }, + "testvectors": [ + { + "name": "AWS Single Period $number$", + "url": "https://d10gktn8v7end7.cloudfront.net/out/v1/6ee19df3afa24fe190a8ae16c2c88560/index.mpd", + "type": "live", + "includedTestfiles": [ + "playback-advanced/cmcd" + ] + } + ] +} diff --git a/test/functional/config/test-configurations/local/smoke.json b/test/functional/config/test-configurations/streams/smoke.json similarity index 92% rename from test/functional/config/test-configurations/local/smoke.json rename to test/functional/config/test-configurations/streams/smoke.json index 0af1fc8040..e66d650bb0 100644 --- a/test/functional/config/test-configurations/local/smoke.json +++ b/test/functional/config/test-configurations/streams/smoke.json @@ -1,7 +1,4 @@ { - "browsers": [ - "chrome_custom" - ], "testfiles": { "included": [ "all" @@ -124,20 +121,17 @@ ] }, { - "name": "AWS Multiperiod unencrypted", + "name": "DASH-IF Multiperiod Segment Template", "type": "live", - "url": "https://d24rwxnt7vw9qb.cloudfront.net/v1/dash/e6d234965645b411ad572802b6c9d5a10799c9c1/All_Reference_Streams/4577dca5f8a44756875ab5cc913cd1f1/index.mpd", + "url": "https://livesim2.dashif.org/livesim2/periods_60/continuous_1/testpic_2s/Manifest.mpd", "testdata": { "periods": { "waitingTimeForPeriodSwitches": 70000, "minimumNumberOfPeriodSwitches": 1, - "maximumNumberOfPeriodSwitches": 15 + "maximumNumberOfPeriodSwitches": 2 } }, "includedTestfiles": [ - "playback/play", - "playback/pause", - "playback/seek", "playback-advanced/multiperiod-playback" ] }, diff --git a/test/functional/config/test-configurations/local/text.json b/test/functional/config/test-configurations/streams/text.json similarity index 89% rename from test/functional/config/test-configurations/local/text.json rename to test/functional/config/test-configurations/streams/text.json index 9da564d57a..bfbce0bc5c 100644 --- a/test/functional/config/test-configurations/local/text.json +++ b/test/functional/config/test-configurations/streams/text.json @@ -1,7 +1,4 @@ { - "browsers": [ - "chrome_custom" - ], "testfiles": { "included": [ "all" @@ -17,7 +14,7 @@ "provider": "dashif", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -26,7 +23,7 @@ "provider": "dashif", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -35,16 +32,16 @@ "provider": "dashif", "type": "live", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { "name": "TTML Sideloaded XML Subtitles", - "url": "https://livesim2.dashif.org/dash/vod/testpic_2s/xml_subs.mpd", + "url": "https://livesim2.dashif.org/vod/testpic_2s/ttml_subs.mpd", "provider": "dashif", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -53,7 +50,7 @@ "provider": "dashif", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -62,7 +59,7 @@ "provider": "dashif", "type": "live", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -71,7 +68,7 @@ "provider": "dashif", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -80,7 +77,7 @@ "provider": "dashif", "type": "live", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -90,7 +87,7 @@ "provider": "dashif", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -100,7 +97,7 @@ "provider": "dashif", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -110,7 +107,7 @@ "provider": "bbc", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -120,7 +117,7 @@ "provider": "bbc", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -130,7 +127,7 @@ "provider": "bbc", "type": "live", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -140,7 +137,7 @@ "provider": "bbc", "type": "live", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -150,7 +147,7 @@ "provider": "bbc", "type": "live", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -160,7 +157,7 @@ "provider": "bbc", "type": "live", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -169,7 +166,7 @@ "provider": "cta", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] }, { @@ -177,7 +174,7 @@ "name": "Shaka 44 different subtitles", "type": "vod", "includedTestfiles": [ - "text/switch-text" + "text/*" ] } ] diff --git a/test/functional/config/test-configurations/local/vod_live_lowlatency_mss_multiaudio.json b/test/functional/config/test-configurations/streams/vod_live_lowlatency_mss_multiaudio.json similarity index 97% rename from test/functional/config/test-configurations/local/vod_live_lowlatency_mss_multiaudio.json rename to test/functional/config/test-configurations/streams/vod_live_lowlatency_mss_multiaudio.json index 946cb2f5f6..53685a88c6 100644 --- a/test/functional/config/test-configurations/local/vod_live_lowlatency_mss_multiaudio.json +++ b/test/functional/config/test-configurations/streams/vod_live_lowlatency_mss_multiaudio.json @@ -1,7 +1,4 @@ { - "browsers": [ - "chrome_custom" - ], "testfiles": { "included": [ "all" diff --git a/test/functional/src/Constants.js b/test/functional/src/Constants.js index d1b7456183..c96b400a02 100644 --- a/test/functional/src/Constants.js +++ b/test/functional/src/Constants.js @@ -147,7 +147,7 @@ TESTCASES.PLAYBACK.PLAY = TESTCASES.CATEGORIES.PLAYBACK + 'play'; TESTCASES.PLAYBACK.SEEK = TESTCASES.CATEGORIES.PLAYBACK + 'seek'; TESTCASES.PLAYBACK_ADVANCED.ATTACH_AT_NON_ZERO = TESTCASES.CATEGORIES.PLAYBACK_ADVANCED + 'attach-at-non-zero'; -TESTCASES.PLAYBACK_ADVANCED.ATTACH_WITH_POSIX = TESTCASES.CATEGORIES.PLAYBACK_ADVANCED + 'simple-attach-with-posix'; +TESTCASES.PLAYBACK_ADVANCED.ATTACH_WITH_POSIX = TESTCASES.CATEGORIES.PLAYBACK_ADVANCED + 'attach-with-posix'; TESTCASES.PLAYBACK_ADVANCED.MPD_ANCHOR = TESTCASES.CATEGORIES.PLAYBACK_ADVANCED + 'mpd-anchor'; TESTCASES.PLAYBACK_ADVANCED.MULTIPERIOD_PLAYBACK = TESTCASES.CATEGORIES.PLAYBACK_ADVANCED + 'multiperiod-playback'; TESTCASES.PLAYBACK_ADVANCED.CMCD = TESTCASES.CATEGORIES.PLAYBACK_ADVANCED + 'cmcd'; diff --git a/test/functional/test/playback-advanced/attach-at-non-zero.js b/test/functional/test/playback-advanced/attach-at-non-zero.js index 4d77b8f6ce..e63d0d11e6 100644 --- a/test/functional/test/playback-advanced/attach-at-non-zero.js +++ b/test/functional/test/playback-advanced/attach-at-non-zero.js @@ -60,10 +60,9 @@ Utils.getTestvectorsForTestcase(TESTCASE).forEach((item) => { startTime = playerAdapter.isDynamic() ? startTime - Constants.TEST_INPUTS.ATTACH_AT_NON_ZERO.LIVE_RANDOM_ATTACH_SUBTRACT_OFFSET : startTime - Constants.TEST_INPUTS.ATTACH_AT_NON_ZERO.VOD_RANDOM_ATTACH_SUBTRACT_OFFSET; startTime = Math.max(startTime, 0); playerAdapter.attachSource(mpd, startTime); - + playerAdapter.pause(); let seeked = await playerAdapter.waitForEvent(Constants.TEST_TIMEOUT_THRESHOLDS.EVENT_WAITING_TIME, dashjs.MediaPlayer.events.PLAYBACK_SEEKED); expect(seeked).to.be.true; - const targetTime = playerAdapter.isDynamic() ? startTime - playerAdapter.getDvrSeekOffset(0) : startTime; checkTimeWithinThreshold(playerAdapter, targetTime, Constants.TEST_INPUTS.GENERAL.MAXIMUM_ALLOWED_SEEK_DIFFERENCE); }); diff --git a/test/functional/test/playback-advanced/attach-with-posix.js b/test/functional/test/playback-advanced/attach-with-posix.js index aa8bd798bc..e37698daa2 100644 --- a/test/functional/test/playback-advanced/attach-with-posix.js +++ b/test/functional/test/playback-advanced/attach-with-posix.js @@ -1,7 +1,5 @@ -import DashJsAdapter from '../../adapter/DashJsAdapter.js'; import Constants from '../../src/Constants.js'; import Utils from '../../src/Utils.js'; -import {expect} from 'chai' import { checkIsPlaying, checkIsProgressing, diff --git a/test/functional/test/playback-advanced/cmcd.js b/test/functional/test/playback-advanced/cmcd.js index 42ed383682..b07cb2f16a 100644 --- a/test/functional/test/playback-advanced/cmcd.js +++ b/test/functional/test/playback-advanced/cmcd.js @@ -49,13 +49,17 @@ Utils.getTestvectorsForTestcase(TESTCASE).forEach((item) => { it(`Expect requests to have CMCD query parameters`, async () => { const eventPayload = await playerAdapter.waitForMediaSegmentDownload(Constants.TEST_TIMEOUT_THRESHOLDS.EVENT_WAITING_TIME) + expect(eventPayload.request).to.not.be.undefined; + expect(eventPayload.request.url).to.not.be.undefined; const requestUrl = eventPayload.request.url; const url = new URL(requestUrl); const cmcdString = url.searchParams.get('CMCD'); const cmcdParams = {} cmcdString.split(',').forEach(pair => { const [key, value] = pair.split('='); - cmcdParams[key] = value.replace(/"/g, ''); + if (value) { + cmcdParams[key] = value.replace(/"/g, ''); + } }); expect(cmcdParams.sid).to.be.equal('sid'); diff --git a/test/functional/test/text/initial-text.js b/test/functional/test/text/initial-text.js index 5d8b79ced2..ff14a8b732 100644 --- a/test/functional/test/text/initial-text.js +++ b/test/functional/test/text/initial-text.js @@ -34,7 +34,7 @@ Utils.getTestvectorsForTestcase(TESTCASE).forEach((item) => { await checkIsProgressing(playerAdapter); }); - it(`Set initial audio track`, async () => { + it(`Set initial text track`, async () => { availableTextTracks = playerAdapter.getTracksFor(Constants.DASH_JS.MEDIA_TYPES.TEXT); for (let i = 0; i < availableTextTracks.length; i++) {