static createFakeNetworkingEngine(getInitSegment, getSegment, delays) {
    const netEngine = new shaka.test.FakeNetworkingEngine();

    netEngine.request.and.callFake((requestType, request, context) => {
      expect(requestType).toBeTruthy();
      expect(request.uris.length).toBe(1);

      const parts = request.uris[0].split('_');
      if (parts[3] === 'secondaryAudioVariant') {
        expect(parts.length).toBe(4);
      } else {
        expect(parts.length).toBeGreaterThanOrEqual(3);
      }

      const periodIndex = Number(parts[0]);
      expect(periodIndex).not.toBeNaN();
      expect(periodIndex).toBeGreaterThan(-1);
      expect(Math.floor(periodIndex)).toBe(periodIndex);

      const contentType = parts[1];

      let buffer;
      const chunkedData = new Uint8Array([
        0x00, 0x00, 0x00, 0x0C, // size
        0x6d, 0x64, 0x61, 0x74, // type: mdat
        0x00, 0x11, 0x22, 0x33, // payload
      ]);

      if (parts[2] == 'init') {
        buffer = getInitSegment(contentType, periodIndex);
      } else {
        const position = Number(parts[2]);
        expect(position).not.toBeNaN();
        expect(position).toBeGreaterThan(-1);
        expect(Math.floor(position)).toBe(position);
        buffer = getSegment(contentType, periodIndex, position);

        // Mock that each segment request gets the response of a ReadableStream
        // with two chunks of data, each contains one MDAT box.
        // The streamDataCallback function gets called twice.
        if (request.streamDataCallback) {
          request.streamDataCallback(chunkedData);
          request.streamDataCallback(chunkedData);
        }

        if (buffer == null) {
          return shaka.util.AbortableOperation.failed(new shaka.util.Error(
              shaka.util.Error.Severity.CRITICAL,
              shaka.util.Error.Category.NETWORK,
              shaka.util.Error.Code.BAD_HTTP_STATUS,
              '', 404));
        }
      }

      const response = {uri: request.uris[0], data: buffer, headers: {}};
      const p = new Promise((resolve) => {
        setTimeout(() => {
          resolve(response);
        }, delays[contentType] * 1000);
      });
      return shaka.util.AbortableOperation.notAbortable(p);
    });

    return netEngine;
  }
Creates a FakeNetworkingEngine.

For each request, the FakeNetworkingEngine parses the request's URI and
invokes one of the provided callbacks to obtain a response.

A request's URI must follow either the init segment URI pattern:
PERIOD_TYPE_init, e.g., "1_audio_init" or "2_video_init"; or the media
segment URI pattern: PERIOD_TYPE_POSITION, e.g., "1_text_2" or "2_video_5".

@param {function(string, number): BufferSource} getInitSegment Init segment
  generator: takes a content type and a Period number; returns an init
  segment.
@param {function(string, number, number): ?BufferSource} getSegment Media
  segment generator: takes a content type, a Period number, and a segment
  position; returns a media segment.
@param {{audio: number, video: number, text: number}} delays Artificial
  delays per content type, in seconds.
@return {!shaka.test.FakeNetworkingEngine}