Back to Repositories

Testing FLAC Binary Search Seeking Implementation in SmartTube

The FlacBinarySearchSeekerTest suite validates the binary search seeking functionality in FLAC audio files within the ExoPlayer framework. This test suite specifically focuses on seeking capabilities in FLAC files without seek tables, ensuring accurate audio positioning and duration handling.

Test Coverage Overview

The test suite provides comprehensive coverage of the FlacBinarySearchSeeker component.

Key areas tested include:
  • Seek map generation and validation
  • Duration calculation accuracy
  • Seeking functionality verification
  • Handling of FLAC files without seek tables
Edge cases specifically address files lacking traditional seek tables, ensuring robust seeking capabilities.

Implementation Analysis

The testing approach utilizes JUnit4 with AndroidJUnit4 runner for Android-specific test execution. The implementation employs fake extractor inputs and mock data to simulate FLAC file processing.

Key patterns include:
  • Setup validation using FlacLibrary availability checks
  • Binary search seeking validation
  • Stream metadata decoding verification
  • Seek position accuracy testing

Technical Details

Testing tools and configuration:
  • JUnit4 testing framework
  • AndroidJUnit4 test runner
  • FakeExtractorInput for simulated data streams
  • FlacDecoderJni for native code integration
  • TestUtil for resource handling
  • Custom FLAC test files (bear_no_seek.flac)

Best Practices Demonstrated

The test suite exemplifies high-quality testing practices through systematic validation of FLAC seeking functionality.

Notable practices include:
  • Proper test initialization and cleanup
  • Thorough validation of seek map properties
  • Clear separation of test cases
  • Effective use of assertion methods
  • Comprehensive error handling verification

yuliskov/smarttube

exoplayer-amzn-2.10.6/extensions/flac/src/androidTest/java/com/google/android/exoplayer2/ext/flac/FlacBinarySearchSeekerTest.java

            
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.android.exoplayer2.ext.flac;

import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;

import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.google.android.exoplayer2.extractor.SeekMap;
import com.google.android.exoplayer2.testutil.FakeExtractorInput;
import com.google.android.exoplayer2.testutil.TestUtil;
import java.io.IOException;
import org.junit.Before;
import org.junit.runner.RunWith;

/** Unit test for {@link FlacBinarySearchSeeker}. */
@RunWith(AndroidJUnit4.class)
public final class FlacBinarySearchSeekerTest {

  private static final String NOSEEKTABLE_FLAC = "bear_no_seek.flac";
  private static final int DURATION_US = 2_741_000;

  @Before
  public void setUp() {
    if (!FlacLibrary.isAvailable()) {
      fail("Flac library not available.");
    }
  }

  public void testGetSeekMap_returnsSeekMapWithCorrectDuration()
      throws IOException, FlacDecoderException, InterruptedException {
    byte[] data =
        TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), NOSEEKTABLE_FLAC);

    FakeExtractorInput input = new FakeExtractorInput.Builder().setData(data).build();
    FlacDecoderJni decoderJni = new FlacDecoderJni();
    decoderJni.setData(input);

    FlacBinarySearchSeeker seeker =
        new FlacBinarySearchSeeker(
            decoderJni.decodeStreamMetadata(),
            /* firstFramePosition= */ 0,
            data.length,
            decoderJni);

    SeekMap seekMap = seeker.getSeekMap();
    assertThat(seekMap).isNotNull();
    assertThat(seekMap.getDurationUs()).isEqualTo(DURATION_US);
    assertThat(seekMap.isSeekable()).isTrue();
  }

  public void testSetSeekTargetUs_returnsSeekPending()
      throws IOException, FlacDecoderException, InterruptedException {
    byte[] data =
        TestUtil.getByteArray(ApplicationProvider.getApplicationContext(), NOSEEKTABLE_FLAC);

    FakeExtractorInput input = new FakeExtractorInput.Builder().setData(data).build();
    FlacDecoderJni decoderJni = new FlacDecoderJni();
    decoderJni.setData(input);
    FlacBinarySearchSeeker seeker =
        new FlacBinarySearchSeeker(
            decoderJni.decodeStreamMetadata(),
            /* firstFramePosition= */ 0,
            data.length,
            decoderJni);

    seeker.setSeekTargetUs(/* timeUs= */ 1000);
    assertThat(seeker.isSeeking()).isTrue();
  }
}