MultiModelLoaderFactoryTest.java 13.1 KB
Newer Older
1 2
package com.bumptech.glide.load.model;

S
Sam Judd 已提交
3
import static com.google.common.truth.Truth.assertThat;
4
import static org.junit.Assert.assertThrows;
S
Sam Judd 已提交
5 6 7 8 9
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

10
import android.support.v4.util.Pools.Pool;
11
import com.bumptech.glide.Registry.NoModelLoaderAvailableException;
R
Robert Papp 已提交
12
import com.bumptech.glide.tests.Util;
13
import com.bumptech.glide.util.pool.FactoryPools;
J
judds 已提交
14 15
import java.util.ArrayList;
import java.util.List;
16 17
import org.junit.Before;
import org.junit.Test;
18
import org.junit.function.ThrowingRunnable;
19
import org.junit.runner.RunWith;
20
import org.mockito.ArgumentCaptor;
21 22
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
S
Sam Judd 已提交
23
import org.robolectric.RobolectricTestRunner;
24 25
import org.robolectric.annotation.Config;

S
Sam Judd 已提交
26 27
// containsExactly produces a spurious warning.
@SuppressWarnings("ResultOfMethodCallIgnored")
28
@RunWith(RobolectricTestRunner.class)
29
@Config(manifest = Config.NONE, sdk = 18)
30
public class MultiModelLoaderFactoryTest {
S
Sam Judd 已提交
31 32 33 34 35
  @Mock private ModelLoaderFactory<String, String> firstFactory;
  @Mock private ModelLoader<String, String> firstModelLoader;
  @Mock private MultiModelLoaderFactory.Factory multiModelLoaderFactory;
  @Mock private ModelLoaderFactory<String, String> secondFactory;
  @Mock private ModelLoader<String, String> secondModelLoader;
S
Sam Judd 已提交
36

37
  private Pool<List<Throwable>> throwableListPool;
S
Sam Judd 已提交
38 39 40 41 42
  private MultiModelLoaderFactory multiFactory;

  @Before
  public void setUp() {
    MockitoAnnotations.initMocks(this);
43
    throwableListPool = FactoryPools.threadSafeList();
S
Sam Judd 已提交
44

45 46
    multiFactory =
        new MultiModelLoaderFactory(throwableListPool, multiModelLoaderFactory);
47 48
    when(firstFactory.build(eq(multiFactory))).thenReturn(firstModelLoader);
    when(secondFactory.build(eq(multiFactory))).thenReturn(secondModelLoader);
S
Sam Judd 已提交
49 50 51 52
  }

  @Test
  public void testAppend_addsModelLoaderForModelClass() {
53
    multiFactory.append(String.class, String.class, firstFactory);
S
Sam Judd 已提交
54 55

    List<ModelLoader<String, ?>> modelLoaders = multiFactory.build(String.class);
56
    assertThat(modelLoaders).containsExactly(firstModelLoader);
S
Sam Judd 已提交
57 58 59 60
  }

  @Test
  public void testAppend_addsModelLoaderForModelAndDataClass() {
61
    multiFactory.append(String.class, String.class, firstFactory);
S
Sam Judd 已提交
62

63 64
    ModelLoader<String, String> modelLoader = multiFactory.build(String.class, String.class);
    assertThat(modelLoader).isEqualTo(firstModelLoader);
S
Sam Judd 已提交
65 66 67 68
  }

  @Test
  public void testPrepend_addsModelLoaderForModelClass() {
69
    multiFactory.prepend(String.class, String.class, firstFactory);
S
Sam Judd 已提交
70 71

    List<ModelLoader<String, ?>> modelLoaders = multiFactory.build(String.class);
72
    assertThat(modelLoaders).containsExactly(firstModelLoader);
S
Sam Judd 已提交
73 74 75 76
  }

  @Test
  public void testPrepend_addsModelLoaderForModelAndDataClass() {
77
    multiFactory.prepend(String.class, String.class, firstFactory);
S
Sam Judd 已提交
78

79 80
    ModelLoader<String, String> modelLoader = multiFactory.build(String.class, String.class);
    assertThat(modelLoader).isEqualTo(firstModelLoader);
S
Sam Judd 已提交
81 82 83 84
  }

  @Test
  public void testReplace_addsModelLoaderForModelClass() {
85
    multiFactory.replace(String.class, String.class, firstFactory);
S
Sam Judd 已提交
86 87

    List<ModelLoader<String, ?>> modelLoaders = multiFactory.build(String.class);
88
    assertThat(modelLoaders).containsExactly(firstModelLoader);
S
Sam Judd 已提交
89 90 91 92
  }

  @Test
  public void testReplace_addsModelLoaderForModelAndDataClasses() {
93
    multiFactory.replace(String.class, String.class, firstFactory);
S
Sam Judd 已提交
94

95 96
    ModelLoader<String, String> modelLoader = multiFactory.build(String.class, String.class);
    assertThat(modelLoader).isEqualTo(firstModelLoader);
S
Sam Judd 已提交
97 98 99 100
  }

  @Test
  public void testReplace_returnsPreviouslyRegisteredFactories_withModelAndDataClasses() {
R
Robert Papp 已提交
101 102
    ModelLoaderFactory<String, String> firstOtherFactory = mockFactory();
    ModelLoaderFactory<String, String> secondOtherFactory = mockFactory();
S
Sam Judd 已提交
103 104 105
    multiFactory.append(String.class, String.class, firstOtherFactory);
    multiFactory.append(String.class, String.class, secondOtherFactory);

S
Sam Judd 已提交
106
    List<ModelLoaderFactory<? extends String, ? extends String>> removed =
107
        multiFactory.replace(String.class, String.class, firstFactory);
S
Sam Judd 已提交
108 109
    assertThat(removed).containsExactly(firstOtherFactory, secondOtherFactory);
  }
110

S
Sam Judd 已提交
111 112 113 114
  @Test
  public void testReplace_removesPreviouslyRegisteredFactories_withModelAndDataClasses() {
    appendFactoryFor(String.class, String.class);
    appendFactoryFor(String.class, String.class);
115

116
    multiFactory.replace(String.class, String.class, firstFactory);
117

S
Sam Judd 已提交
118
    List<ModelLoader<String, ?>> modelLoaders = multiFactory.build(String.class);
119
    assertThat(modelLoaders).containsExactly(firstModelLoader);
S
Sam Judd 已提交
120
  }
121

S
Sam Judd 已提交
122 123
  @Test
  public void testRemove_returnsPreviouslyRegisteredFactories_withModelAndDataClasses() {
R
Robert Papp 已提交
124
    ModelLoaderFactory<String, String> other = mockFactory();
S
Sam Judd 已提交
125
    multiFactory.append(String.class, String.class, other);
126
    multiFactory.append(String.class, String.class, firstFactory);
127

S
Sam Judd 已提交
128
    List<ModelLoaderFactory<? extends String, ? extends String>> removed =
129
        multiFactory.remove(String.class, String.class);
130
    assertThat(removed).containsExactly(firstFactory, other);
S
Sam Judd 已提交
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
  }

  @Test
  public void testRemove_removesPreviouslyRegisteredFactories_withModelAndDataClasses() {
    appendFactoryFor(String.class, String.class);
    appendFactoryFor(String.class, String.class);

    multiFactory.remove(String.class, String.class);

    List<ModelLoader<String, ?>> modelLoaders = multiFactory.build(String.class);
    assertThat(modelLoaders).isEmpty();
  }

  @Test
  public void testBuild_withModelClass_returnsMultipleModelLoaders_ofGivenModelAndDataClasses() {
    ModelLoader<String, String> otherLoader = appendFactoryFor(String.class, String.class);
147
    multiFactory.append(String.class, String.class, firstFactory);
S
Sam Judd 已提交
148 149

    List<ModelLoader<String, ?>> modelLoaders = multiFactory.build(String.class);
150
    assertThat(modelLoaders).containsExactly(otherLoader, firstModelLoader);
S
Sam Judd 已提交
151 152 153 154 155 156
  }

  @Test
  public void
  testBuild_withModelClass_returnsMultipleModelLoaders_ofGivenModelClassWithDifferentDataClasses() {
    ModelLoader<String, Integer> otherLoader = appendFactoryFor(String.class, Integer.class);
157
    multiFactory.append(String.class, String.class, firstFactory);
S
Sam Judd 已提交
158 159

    List<ModelLoader<String, ?>> modelLoaders = multiFactory.build(String.class);
160
    assertThat(modelLoaders).containsExactly(otherLoader, firstModelLoader);
S
Sam Judd 已提交
161 162 163 164
  }

  @Test
  public void testBuild_withModelClass_excludesModelLoadersForOtherModelClasses() {
165
    multiFactory.append(String.class, String.class, firstFactory);
S
Sam Judd 已提交
166
    List<ModelLoader<Integer, ?>> modelLoaders = multiFactory.build(Integer.class);
167
    assertThat(modelLoaders).doesNotContain(firstModelLoader);
S
Sam Judd 已提交
168 169 170 171 172 173
  }

  @Test
  public void
  testBuild_withModelAndDataClasses_returnsMultipleModelLoaders_ofGivenModelAndDataClasses() {
    ModelLoader<String, String> otherLoader = appendFactoryFor(String.class, String.class);
174
    multiFactory.append(String.class, String.class, firstFactory);
S
Sam Judd 已提交
175 176

    List<ModelLoader<String, String>> modelLoaders = buildModelLoaders(String.class, String.class);
177
    assertThat(modelLoaders).containsExactly(otherLoader, firstModelLoader);
S
Sam Judd 已提交
178 179 180 181
  }

  @Test
  public void testBuild_withModelAndDataClasses_excludesModelLoadersForOtherDataClasses() {
182 183
    multiFactory.append(String.class, String.class, firstFactory);

184 185 186 187 188 189 190 191
    assertThrows(
        NoModelLoaderAvailableException.class,
        new ThrowingRunnable() {
          @Override
          public void run() throws Throwable {
            multiFactory.build(String.class, Integer.class);
          }
        });
S
Sam Judd 已提交
192 193 194 195
  }

  @Test
  public void testBuild_withModelAndDataClasses_excludesModelLoadersForOtherModelClasses() {
196 197
    multiFactory.append(String.class, String.class, firstFactory);

198 199 200 201 202 203 204 205
    assertThrows(
        NoModelLoaderAvailableException.class,
        new ThrowingRunnable() {
          @Override
          public void run() throws Throwable {
            multiFactory.build(Integer.class, String.class);
          }
        });
S
Sam Judd 已提交
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
  }

  @Test
  public void testBuild_withModelClass_doesNotMatchSubclassesOfModelClass() {
    ModelLoader<String, Object> subclass = appendFactoryFor(String.class, Object.class);
    List<ModelLoader<Object, ?>> modelLoaders = multiFactory.build(Object.class);
    assertThat(modelLoaders).doesNotContain(subclass);
  }

  @Test
  public void testBuild_withModelClass_matchesSuperclassesOfModelClass() {
    ModelLoader<Object, Object> superclass = appendFactoryFor(Object.class, Object.class);
    List<ModelLoader<String, ?>> modelLoaders = multiFactory.build(String.class);
    assertThat(modelLoaders).contains(superclass);
  }

  @Test
  public void testBuild_withModelAndDataClass_doesNotMatchSubclassesOfModelClass() {
224
    appendFactoryFor(String.class, Object.class);
225 226 227 228 229 230 231 232 233

    assertThrows(
        NoModelLoaderAvailableException.class,
        new ThrowingRunnable() {
          @Override
          public void run() throws Throwable {
            multiFactory.build(Object.class, Object.class);
          }
        });
S
Sam Judd 已提交
234 235 236 237
  }

  @Test
  public void testBuild_withModelAndDataClass_doesNotMatchSubclassesOfDataClass() {
238
    appendFactoryFor(Object.class, String.class);
239 240 241 242 243 244 245 246
    assertThrows(
        NoModelLoaderAvailableException.class,
        new ThrowingRunnable() {
          @Override
          public void run() throws Throwable {
            multiFactory.build(Object.class, Object.class);
          }
        });
S
Sam Judd 已提交
247 248 249 250
  }

  @Test
  public void testBuild_withModelAndDataClass_doesMatchSuperclassesOfModelClass() {
251 252
    ModelLoader<Object, Object> firstSuperClass = appendFactoryFor(Object.class, Object.class);
    ModelLoader<Object, Object> secondSuperClass = appendFactoryFor(Object.class, Object.class);
S
Sam Judd 已提交
253
    List<ModelLoader<String, Object>> modelLoaders = buildModelLoaders(String.class, Object.class);
254
    assertThat(modelLoaders).containsExactly(firstSuperClass, secondSuperClass);
S
Sam Judd 已提交
255 256 257 258
  }

  @Test
  public void testBuild_withModelAndDataClass_matchesSuperclassesOfDataClass() {
259 260
    ModelLoader<Object, Object> firstSuperClass = appendFactoryFor(Object.class, Object.class);
    ModelLoader<Object, Object> secondSuperClass = appendFactoryFor(Object.class, Object.class);
S
Sam Judd 已提交
261
    List<ModelLoader<Object, String>> modelLoaders = buildModelLoaders(Object.class, String.class);
262
    assertThat(modelLoaders).containsExactly(firstSuperClass, secondSuperClass);
S
Sam Judd 已提交
263 264 265 266
  }

  @Test
  public void testBuild_withModelAndDataClass_matchesSuperclassOfModelAndDataClass() {
267 268
    ModelLoader<Object, Object> firstSuperclass = appendFactoryFor(Object.class, Object.class);
    ModelLoader<Object, Object> secondSuperclass = appendFactoryFor(Object.class, Object.class);
S
Sam Judd 已提交
269
    List<ModelLoader<String, String>> modelLoaders = buildModelLoaders(String.class, String.class);
270
    assertThat(modelLoaders).containsExactly(firstSuperclass, secondSuperclass);
S
Sam Judd 已提交
271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
  }

  @Test
  public void testBuild_respectsAppendOrder() {
    ModelLoader<String, String> first = appendFactoryFor(String.class, String.class);
    ModelLoader<String, String> second = appendFactoryFor(String.class, String.class);
    ModelLoader<String, String> third = appendFactoryFor(String.class, String.class);
    List<ModelLoader<String, String>> modelLoaders = buildModelLoaders(String.class, String.class);
    assertThat(modelLoaders).containsExactly(first, second, third).inOrder();
  }

  @Test
  public void testBuild_respectsPrependOrder() {
    ModelLoader<String, String> first = prependFactoryFor(String.class, String.class);
    ModelLoader<String, String> second = prependFactoryFor(String.class, String.class);
    ModelLoader<String, String> third = prependFactoryFor(String.class, String.class);
    List<ModelLoader<String, String>> modelLoaders = buildModelLoaders(String.class, String.class);
    assertThat(modelLoaders).containsExactly(third, second, first).inOrder();
  }

  private <X, Y> List<ModelLoader<X, Y>> buildModelLoaders(Class<X> modelClass,
      Class<Y> dataClass) {
R
Robert Papp 已提交
293
    ArgumentCaptor<List<ModelLoader<X, Y>>> captor = Util.cast(ArgumentCaptor.forClass(List.class));
S
Sam Judd 已提交
294
    multiFactory.build(modelClass, dataClass);
295
    verify(multiModelLoaderFactory).build(captor.capture(), eq(throwableListPool));
S
Sam Judd 已提交
296

R
Robert Papp 已提交
297
    List<ModelLoader<X, Y>> captured = captor.getValue();
S
Sam Judd 已提交
298
    List<ModelLoader<X, Y>> result = new ArrayList<>(captured.size());
S
Sam Judd 已提交
299
    result.addAll(captured);
S
Sam Judd 已提交
300 301 302 303 304 305 306 307 308 309 310
    return result;
  }

  private <X, Y> ModelLoader<X, Y> appendFactoryFor(Class<X> modelClass, Class<Y> dataClass) {
    return registerFactoryFor(modelClass, dataClass, true /*append*/);
  }

  private <X, Y> ModelLoader<X, Y> prependFactoryFor(Class<X> modelClass, Class<Y> dataClass) {
    return registerFactoryFor(modelClass, dataClass, false /*append*/);
  }

R
Robert Papp 已提交
311 312 313 314
  private <X, Y> ModelLoader<X, Y> registerFactoryFor(
      Class<X> modelClass, Class<Y> dataClass, boolean append) {
    ModelLoaderFactory<X, Y> factory = mockFactory();
    @SuppressWarnings("unchecked") ModelLoader<X, Y> loader = mock(ModelLoader.class);
315
    when(factory.build(eq(multiFactory))).thenReturn(loader);
S
Sam Judd 已提交
316 317 318 319
    if (append) {
      multiFactory.append(modelClass, dataClass, factory);
    } else {
      multiFactory.prepend(modelClass, dataClass, factory);
320
    }
S
Sam Judd 已提交
321 322
    return loader;
  }
R
Robert Papp 已提交
323 324 325 326 327

  @SuppressWarnings("unchecked")
  private static <X, Y> ModelLoaderFactory<X, Y> mockFactory() {
    return mock(ModelLoaderFactory.class);
  }
328 329
}