@Test
public void testNestedTimeline() throws IOException {

  ConcatenatingMediaSource nestedSource1 =
      new ConcatenatingMediaSource(/* isAtomic= */ false, new FakeShuffleOrder(0));
  ConcatenatingMediaSource nestedSource2 =
      new ConcatenatingMediaSource(/* isAtomic= */ true, new FakeShuffleOrder(0));
  mediaSource.addMediaSource(nestedSource1);
  mediaSource.addMediaSource(nestedSource2);
  testRunner.prepareSource();
  FakeMediaSource[] childSources = createMediaSources(4);
  nestedSource1.addMediaSource(childSources[0]);
  testRunner.assertTimelineChangeBlocking();
  nestedSource1.addMediaSource(childSources[1]);
  testRunner.assertTimelineChangeBlocking();
  nestedSource2.addMediaSource(childSources[2]);
  testRunner.assertTimelineChangeBlocking();
  nestedSource2.addMediaSource(childSources[3]);
  Timeline timeline = testRunner.assertTimelineChangeBlocking();
  TimelineAsserts.assertWindowTags(timeline, 111, 222, 333, 444);
  TimelineAsserts.assertPeriodCounts(timeline, 1, 2, 3, 4);
  TimelineAsserts.assertPreviousWindowIndices(
      timeline, Player.REPEAT_MODE_OFF, /* shuffleModeEnabled= */ false, C.INDEX_UNSET, 0, 1, 2);
  TimelineAsserts.assertPreviousWindowIndices(
      timeline, Player.REPEAT_MODE_ONE, /* shuffleModeEnabled= */ false, 0, 1, 3, 2);
  TimelineAsserts.assertPreviousWindowIndices(
      timeline, Player.REPEAT_MODE_ALL, /* shuffleModeEnabled= */ false, 3, 0, 1, 2);
  TimelineAsserts.assertNextWindowIndices(
      timeline, Player.REPEAT_MODE_OFF, /* shuffleModeEnabled= */ false, 1, 2, 3, C.INDEX_UNSET);
  TimelineAsserts.assertNextWindowIndices(
      timeline, Player.REPEAT_MODE_ONE, /* shuffleModeEnabled= */ false, 0, 1, 3, 2);
  TimelineAsserts.assertNextWindowIndices(
      timeline, Player.REPEAT_MODE_ALL, /* shuffleModeEnabled= */ false, 1, 2, 3, 0);
  TimelineAsserts.assertPreviousWindowIndices(
      timeline, Player.REPEAT_MODE_OFF, /* shuffleModeEnabled= */ true, 1, 3, C.INDEX_UNSET, 2);
  TimelineAsserts.assertPreviousWindowIndices(
      timeline, Player.REPEAT_MODE_ONE, /* shuffleModeEnabled= */ true, 0, 1, 3, 2);
  TimelineAsserts.assertPreviousWindowIndices(
      timeline, Player.REPEAT_MODE_ALL, /* shuffleModeEnabled= */ true, 1, 3, 0, 2);
  TimelineAsserts.assertNextWindowIndices(
      timeline, Player.REPEAT_MODE_OFF, /* shuffleModeEnabled= */ true, C.INDEX_UNSET, 0, 3, 1);
  TimelineAsserts.assertNextWindowIndices(
      timeline, Player.REPEAT_MODE_ONE, /* shuffleModeEnabled= */ true, 0, 1, 3, 2);
  TimelineAsserts.assertNextWindowIndices(
      timeline, Player.REPEAT_MODE_ALL, /* shuffleModeEnabled= */ true, 2, 0, 3, 1);
}