Back to Repositories

Testing Bitmap Attribute Strategy Implementation in Glide

This test suite validates the AttributeStrategy class in Glide’s bitmap recycling system, focusing on bitmap attribute matching and caching behavior. It ensures proper handling of bitmap dimensions, configurations, and least-recently-used (LRU) functionality.

Test Coverage Overview

The test suite provides comprehensive coverage of bitmap attribute matching and recycling logic.

Key areas tested include:
  • Null handling for non-matching bitmaps
  • Dimension matching (width/height)
  • Bitmap configuration compatibility
  • Multiple bitmap handling
  • LRU eviction behavior

Implementation Analysis

The testing approach employs JUnit with Robolectric for Android bitmap operations simulation. Tests follow a systematic pattern of creating bitmaps with specific attributes, adding them to the strategy, and verifying retrieval behavior.

Framework features utilized include:
  • @RunWith(RobolectricTestRunner.class) for Android environment simulation
  • @Before setup methods for test initialization
  • Assertion methods for verification

Technical Details

Testing infrastructure includes:
  • JUnit 4 test framework
  • Robolectric for Android SDK simulation
  • Custom SDK version configuration
  • Bitmap.Config variations (ARGB_8888, RGB_565, ALPHA_8)
  • AttributeStrategy implementation for bitmap recycling

Best Practices Demonstrated

The test suite exemplifies strong testing practices through clear organization and thorough validation.

Notable practices include:
  • Isolated test cases for specific functionality
  • Comprehensive edge case coverage
  • Clear test method naming
  • Proper test setup and teardown
  • Explicit assertion messages for debugging

bumptech/glide

library/test/src/test/java/com/bumptech/glide/load/engine/bitmap_recycle/AttributeStrategyTest.java

            
package com.bumptech.glide.load.engine.bitmap_recycle;

import static com.bumptech.glide.RobolectricConstants.ROBOLECTRIC_SDK;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

import android.graphics.Bitmap;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

@RunWith(RobolectricTestRunner.class)
@Config(sdk = ROBOLECTRIC_SDK)
public class AttributeStrategyTest {

  private AttributeStrategy strategy;

  @Before
  public void setUp() throws Exception {
    strategy = new AttributeStrategy();
  }

  @Test
  public void testIGetNullIfNoMatchingBitmapExists() {
    assertNull(strategy.get(100, 100, Bitmap.Config.ARGB_8888));
  }

  @Test
  public void testICanAddAndGetABitmapOfTheSameSizeAndDimensions() {
    Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    strategy.put(bitmap);
    assertEquals(
        bitmap, strategy.get(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888));
  }

  @Test
  public void testICantGetABitmapOfTheSameDimensionsButDifferentConfigs() {
    Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    strategy.put(bitmap);
    assertNull(strategy.get(100, 100, Bitmap.Config.RGB_565));
  }

  @Test
  public void testICantGetABitmapOfTheSameDimensionsAndSizeButDifferentConfigs() {
    Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_4444);
    strategy.put(bitmap);
    assertNull(strategy.get(100, 100, Bitmap.Config.RGB_565));
  }

  @Test
  public void testICantGetABitmapOfDifferentWidths() {
    Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    strategy.put(bitmap);
    assertNull(strategy.get(99, 100, Bitmap.Config.ARGB_8888));
  }

  @Test
  public void testICantGetABitmapOfDifferentHeights() {
    Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    strategy.put(bitmap);
    assertNull(strategy.get(100, 99, Bitmap.Config.ARGB_8888));
  }

  @Test
  public void testICantGetABitmapOfDifferentDimensionsButTheSameSize() {
    Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    strategy.put(bitmap);
    assertNull(strategy.get(50, 200, Bitmap.Config.ARGB_8888));
  }

  @Test
  public void testMultipleBitmapsOfDifferentAttributesCanBeAddedAtOnce() {
    Bitmap first = Bitmap.createBitmap(100, 100, Bitmap.Config.RGB_565);
    Bitmap second = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
    Bitmap third = Bitmap.createBitmap(120, 120, Bitmap.Config.RGB_565);

    strategy.put(first);
    strategy.put(second);
    strategy.put(third);

    assertEquals(first, strategy.get(100, 100, Bitmap.Config.RGB_565));
    assertEquals(second, strategy.get(100, 100, Bitmap.Config.ARGB_8888));
    assertEquals(third, strategy.get(120, 120, Bitmap.Config.RGB_565));
  }

  @Test
  public void testLeastRecentlyUsedAttributeSetIsRemovedFirst() {
    final Bitmap leastRecentlyUsed = Bitmap.createBitmap(100, 100, Bitmap.Config.ALPHA_8);
    final Bitmap other = Bitmap.createBitmap(1000, 1000, Bitmap.Config.RGB_565);
    final Bitmap mostRecentlyUsed = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);

    strategy.get(100, 100, Bitmap.Config.ALPHA_8);
    strategy.get(1000, 1000, Bitmap.Config.RGB_565);
    strategy.get(100, 100, Bitmap.Config.ARGB_8888);

    strategy.put(other);
    strategy.put(leastRecentlyUsed);
    strategy.put(mostRecentlyUsed);

    Bitmap removed = strategy.removeLast();
    assertEquals(
        "Expected=" + strategy.logBitmap(leastRecentlyUsed) + " got=" + strategy.logBitmap(removed),
        leastRecentlyUsed,
        removed);
  }
}