static makeTimelineTests(type, extraAttrs, extraChildren) {
    describe('SegmentTimeline', () => {
      const Dash = shaka.test.Dash;
      const ManifestParser = shaka.test.ManifestParser;
      const baseUri = 'http://example.com/';

      /**
       * @param {!Array<string>} timeline
       * @param {string} testAttrs
       * @param {number=} dur
       * @param {number=} startTime
       * @return {string}
       */
      function makeManifestText(timeline, testAttrs, dur, startTime) {
        const start = '<' + type + ' ' + extraAttrs + ' ' + testAttrs + '>';
        const end = '</' + type + '>';
        const lines = [].concat(start, extraChildren, timeline, end);
        return Dash.makeSimpleManifestText(lines, dur, startTime);
      }

      // All tests should have 5 segments and have the relative URIs:
      // s1.mp4  s2.mp4  s3.mp4  s4.mp4  s5.mp4
      it('basic support', async () => {
        const timeline = [
          '<SegmentTimeline>',
          '  <S d="12" t="34" />',
          '  <S d="21" />',
          '  <S d="44" />',
          '  <S d="10" />',
          '  <S d="10" />',
          '</SegmentTimeline>',
        ];
        const source = makeManifestText(timeline, '');
        const references = [
          ManifestParser.makeReference('s1.mp4', 34, 46, baseUri),
          ManifestParser.makeReference('s2.mp4', 46, 67, baseUri),
          ManifestParser.makeReference('s3.mp4', 67, 111, baseUri),
          ManifestParser.makeReference('s4.mp4', 111, 121, baseUri),
          ManifestParser.makeReference('s5.mp4', 121, 131, baseUri),
        ];
        await Dash.testSegmentIndex(source, references);
      });

      it('supports repetitions', async () => {
        const timeline = [
          '<SegmentTimeline>',
          '  <S d="12" t="34" />',
          '  <S d="10" r="2" />',
          '  <S d="44" />',
          '</SegmentTimeline>',
        ];
        const source = makeManifestText(timeline, '');
        const references = [
          ManifestParser.makeReference('s1.mp4', 34, 46, baseUri),
          ManifestParser.makeReference('s2.mp4', 46, 56, baseUri),
          ManifestParser.makeReference('s3.mp4', 56, 66, baseUri),
          ManifestParser.makeReference('s4.mp4', 66, 76, baseUri),
          ManifestParser.makeReference('s5.mp4', 76, 120, baseUri),
        ];
        await Dash.testSegmentIndex(source, references);
      });

      it('supports negative repetitions', async () => {
        const timeline = [
          '<SegmentTimeline>',
          '  <S d="8" t="22" />',
          '  <S d="10" r="-1" />',
          '  <S d="12" t="50" />',
          '  <S d="10" />',
          '</SegmentTimeline>',
        ];
        const source = makeManifestText(timeline, '');
        const references = [
          ManifestParser.makeReference('s1.mp4', 22, 30, baseUri),
          ManifestParser.makeReference('s2.mp4', 30, 40, baseUri),
          ManifestParser.makeReference('s3.mp4', 40, 50, baseUri),
          ManifestParser.makeReference('s4.mp4', 50, 62, baseUri),
          ManifestParser.makeReference('s5.mp4', 62, 72, baseUri),
        ];
        await Dash.testSegmentIndex(source, references);
      });

      it('supports negative repetitions at end', async () => {
        const timeline = [
          '<SegmentTimeline>',
          '  <S d="5" t="5" />',
          '  <S d="10" r="-1" />',
          '</SegmentTimeline>',
        ];
        const source = makeManifestText(timeline, '', /* duration= */ 50);
        const references = [
          ManifestParser.makeReference('s1.mp4', 5, 10, baseUri),
          ManifestParser.makeReference('s2.mp4', 10, 20, baseUri),
          ManifestParser.makeReference('s3.mp4', 20, 30, baseUri),
          ManifestParser.makeReference('s4.mp4', 30, 40, baseUri),
          ManifestParser.makeReference('s5.mp4', 40, 50, baseUri),
        ];
        await Dash.testSegmentIndex(source, references);
      });

      it('gives segment times relative to the presentation', async () => {
        const timeline = [
          '<SegmentTimeline>',
          '  <S t="0" d="10" r="-1" />',
          '</SegmentTimeline>',
        ];
        const source =
            makeManifestText(timeline, '', /* duration= */ 50, /* start= */ 30);
        const references = [
          ManifestParser.makeReference('s1.mp4', 30, 40, baseUri),
          ManifestParser.makeReference('s2.mp4', 40, 50, baseUri),
          ManifestParser.makeReference('s3.mp4', 50, 60, baseUri),
          ManifestParser.makeReference('s4.mp4', 60, 70, baseUri),
          ManifestParser.makeReference('s5.mp4', 70, 80, baseUri),
        ];
        for (const ref of references) {
          ref.timestampOffset = 30;
        }
        await Dash.testSegmentIndex(source, references);
      });

      it('supports @timescale', async () => {
        const timeline = [
          '<SegmentTimeline>',
          '  <S d="4500" t="18000" />',
          '  <S d="9000" />',
          '  <S d="31500" />',
          '  <S d="9000" />',
          '  <S d="9000" />',
          '</SegmentTimeline>',
        ];
        const source = makeManifestText(timeline, 'timescale="9000"');
        const references = [
          ManifestParser.makeReference('s1.mp4', 2, 2.5, baseUri),
          ManifestParser.makeReference('s2.mp4', 2.5, 3.5, baseUri),
          ManifestParser.makeReference('s3.mp4', 3.5, 7, baseUri),
          ManifestParser.makeReference('s4.mp4', 7, 8, baseUri),
          ManifestParser.makeReference('s5.mp4', 8, 9, baseUri),
        ];
        await Dash.testSegmentIndex(source, references);
      });
    });
  }
Makes a set of tests for SegmentTimeline.  This is used to test
SegmentTimeline within both SegmentList and SegmentTemplate.

@param {string} type The type of manifest being tested; either
  'SegmentTemplate' or 'SegmentList'.
@param {string} extraAttrs
@param {!Array<string>} extraChildren