Back to Repositories

Testing Large Image Loading Capabilities in Glide Library

This test suite evaluates Glide’s capability to handle large JPEG images in Android applications. It focuses on testing different loading methods including byte arrays and ByteBuffer, ensuring reliable image loading for large files.

Test Coverage Overview

The test suite covers critical functionality for loading large JPEG images in Glide:
  • Byte array loading implementation
  • ByteBuffer loading with custom model loader
  • Resource URI handling and conversion
  • Large file streaming and memory management

Implementation Analysis

The testing approach utilizes JUnit4 with AndroidJUnit4 runner for Android-specific testing. It implements ConcurrencyHelper for handling asynchronous operations and uses TearDownGlide rule for proper test cleanup.

The tests employ UnitModelLoader for isolated ByteBuffer testing and custom URI building for resource access.

Technical Details

Testing tools and configuration:
  • AndroidJUnit4 test runner
  • ConcurrencyHelper for async operations
  • Custom TearDownGlide rule
  • ApplicationProvider for context access
  • ByteArrayOutputStream for large file handling
  • ContentResolver for resource access

Best Practices Demonstrated

The test suite exemplifies several testing best practices:
  • Proper test cleanup with @Rule implementation
  • Isolated testing using UnitModelLoader
  • Efficient resource handling with streamed reading
  • Null safety checks with Objects.requireNonNull
  • Clear test method naming conventions

bumptech/glide

instrumentation/src/androidTest/java/com/bumptech/glide/LargeImageTest.java

            
package com.bumptech.glide;

import static com.google.common.truth.Truth.assertThat;

import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.net.Uri;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.bumptech.glide.load.model.UnitModelLoader;
import com.bumptech.glide.test.ResourceIds;
import com.bumptech.glide.testutil.ConcurrencyHelper;
import com.bumptech.glide.testutil.TearDownGlide;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.Objects;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
public class LargeImageTest {
  @Rule public final TestRule tearDownGlide = new TearDownGlide();
  private final ConcurrencyHelper concurrency = new ConcurrencyHelper();
  private final Context context = ApplicationProvider.getApplicationContext();

  @Test
  public void loadLargeJpeg_asByteArray_succeeds() throws IOException {
    byte[] data = getLargeImageBytes();
    Bitmap bitmap = concurrency.get(Glide.with(context).asBitmap().load(data).submit());
    assertThat(bitmap).isNotNull();
  }

  @Test
  public void loadLargeJpeg_asByteBuffer_succeeds() throws IOException {
    // Using UnitModelLoader lets us mimic loading the ByteBuffer from some other data type, which
    // reduces the scope of our test.
    Glide.get(context)
        .getRegistry()
        .append(
            ByteBuffer.class, ByteBuffer.class, UnitModelLoader.Factory.<ByteBuffer>getInstance());

    ByteBuffer buffer = ByteBuffer.wrap(getLargeImageBytes());
    Bitmap bitmap = concurrency.get(Glide.with(context).asBitmap().load(buffer).submit());
    assertThat(bitmap).isNotNull();
  }

  private byte[] getLargeImageBytes() throws IOException {
    Resources resources = context.getResources();
    int resourceId = ResourceIds.raw.canonical_large;
    Uri uri =
        new Uri.Builder()
            .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
            .authority(resources.getResourcePackageName(resourceId))
            .appendPath(resources.getResourceTypeName(resourceId))
            .appendPath(resources.getResourceEntryName(resourceId))
            .build();

    InputStream is = Objects.requireNonNull(context.getContentResolver().openInputStream(uri));
    ByteArrayOutputStream os = new ByteArrayOutputStream();
    byte[] buffer = new byte[1024 * 1024 * 5];
    int read;
    while ((read = is.read(buffer, 0, buffer.length)) != -1) {
      os.write(buffer, 0, read);
    }
    return os.toByteArray();
  }
}