// Path: agera/src/main/java/com/google/android/agera/Observables.java
// @NonNull
// public static UpdateDispatcher updateDispatcher() {
//   return new AsyncUpdateDispatcher(null);
// }
// 
// Path: agera/src/main/java/com/google/android/agera/Repositories.java
// @NonNull
// public static <T> MutableRepository<T> mutableRepository(@NonNull final T object) {
//   return new SimpleRepository<>(object);
// }
// 
// Path: extensions/rvadapter/src/main/java/com/google/android/agera/rvadapter/RepositoryAdapter.java
// @NonNull
// public static Builder repositoryAdapter() {
//   return new Builder();
// }
// 
// Path: extensions/rvadapter/src/test/java/com/google/android/agera/rvadapter/test/VerifyingWrappers.java
// @NonNull
// public static ListUpdateCallback verifyingWrapper(
//     @NonNull final ListUpdateCallback mockCallback) {
//   // 'verify()' turns only the next method call on that mock to a verification call, so using
//   // this wrapper to insert 'verify()' for each call when verifying the diff results.
//   return new ListUpdateCallback() {
//     @Override
//     public void onInserted(final int position, final int count) {
//       verify(mockCallback).onInserted(position, count);
//     }
// 
//     @Override
//     public void onRemoved(final int position, final int count) {
//       verify(mockCallback).onRemoved(position, count);
//     }
// 
//     @Override
//     public void onMoved(final int fromPosition, final int toPosition) {
//       verify(mockCallback).onMoved(fromPosition, toPosition);
//     }
// 
//     @Override
//     public void onChanged(final int position, final int count, final Object payload) {
//       verify(mockCallback).onChanged(position, count, payload);
//     }
//   };
// }


import static com.google.android.agera.Observables.updateDispatcher;
import static com.google.android.agera.Repositories.mutableRepository;
import static com.google.android.agera.rvadapter.RepositoryAdapter.repositoryAdapter;
import static com.google.android.agera.rvadapter.test.VerifyingWrappers.verifyingWrapper;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isOneOf;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import static org.robolectric.annotation.Config.NONE;
import static org.robolectric.shadows.ShadowLooper.runUiThreadTasksIncludingDelayedTasks;
import android.support.annotation.NonNull;
import android.support.v7.util.ListUpdateCallback;
import android.support.v7.widget.RecyclerView.AdapterDataObserver;
import com.google.android.agera.MutableRepository;
import com.google.android.agera.UpdateDispatcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

    repository2.accept(REPOSITORY_VALUE_B);
    runUiThreadTasksIncludingDelayedTasks();

    verify(mockPresenter1, never()).getItemCount(any());

    final int itemCount = repositoryAdapter.getItemCount();

    verify(mockPresenter2, never()).getItemCount(REPOSITORY_VALUE_A);
    verify(mockPresenter2).getItemCount(REPOSITORY_VALUE_B);
    assertThat(itemCount, is(
        PRESENTER_1_A_ITEM_COUNT + STATIC_ITEM_COUNT + PRESENTER_2_B_ITEM_COUNT));
    assertThat(repositoryAdapter.getItemId(PRESENTER_1_A_ITEM_COUNT + STATIC_ITEM_COUNT + 4),
        is(100L + STATIC_ITEM_COUNT));
    verify(mockPresenter2, never()).getUpdates(any(), any(), any(ListUpdateCallback.class));
  }

  @Test
  public void shouldApplyPresenter1ChangesWithEventsWhenObserved() {
    repositoryAdapter.getItemCount(); // usage
    when(mockPresenter1.getItemId(REPOSITORY_VALUE_B, 2)).thenReturn(10L);

    repository1.accept(REPOSITORY_VALUE_B);
    runUiThreadTasksIncludingDelayedTasks();

    assertThat(repositoryAdapter.getItemCount(), is(
        PRESENTER_1_B_ITEM_COUNT + STATIC_ITEM_COUNT + PRESENTER_2_A_ITEM_COUNT));
    assertThat(repositoryAdapter.getItemId(2), is(10L + STATIC_ITEM_COUNT));
    verify(mockPresenter1).getUpdates(eq(REPOSITORY_VALUE_A), eq(REPOSITORY_VALUE_B),
        any(ListUpdateCallback.class));
// Path: agera/src/main/java/com/google/android/agera/Observables.java
// @NonNull
// public static UpdateDispatcher updateDispatcher() {
//   return new AsyncUpdateDispatcher(null);
// }
// 
// Path: agera/src/main/java/com/google/android/agera/Repositories.java
// @NonNull
// public static <T> MutableRepository<T> mutableRepository(@NonNull final T object) {
//   return new SimpleRepository<>(object);
// }
// 
// Path: extensions/rvadapter/src/main/java/com/google/android/agera/rvadapter/RepositoryAdapter.java
// @NonNull
// public static Builder repositoryAdapter() {
//   return new Builder();
// }
// 
// Path: extensions/rvadapter/src/test/java/com/google/android/agera/rvadapter/test/VerifyingWrappers.java
// @NonNull
// public static ListUpdateCallback verifyingWrapper(
//     @NonNull final ListUpdateCallback mockCallback) {
//   // 'verify()' turns only the next method call on that mock to a verification call, so using
//   // this wrapper to insert 'verify()' for each call when verifying the diff results.
//   return new ListUpdateCallback() {
//     @Override
//     public void onInserted(final int position, final int count) {
//       verify(mockCallback).onInserted(position, count);
//     }
// 
//     @Override
//     public void onRemoved(final int position, final int count) {
//       verify(mockCallback).onRemoved(position, count);
//     }
// 
//     @Override
//     public void onMoved(final int fromPosition, final int toPosition) {
//       verify(mockCallback).onMoved(fromPosition, toPosition);
//     }
// 
//     @Override
//     public void onChanged(final int position, final int count, final Object payload) {
//       verify(mockCallback).onChanged(position, count, payload);
//     }
//   };
// }


// Path: extensions/rvadapter/src/test/java/com/google/android/agera/rvadapter/RepositoryAdapterFineGrainedEventsTest.java
import static com.google.android.agera.Observables.updateDispatcher;
import static com.google.android.agera.Repositories.mutableRepository;
import static com.google.android.agera.rvadapter.RepositoryAdapter.repositoryAdapter;
import static com.google.android.agera.rvadapter.test.VerifyingWrappers.verifyingWrapper;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isOneOf;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
import static org.robolectric.annotation.Config.NONE;
import static org.robolectric.shadows.ShadowLooper.runUiThreadTasksIncludingDelayedTasks;
import android.support.annotation.NonNull;
import android.support.v7.util.ListUpdateCallback;
import android.support.v7.widget.RecyclerView.AdapterDataObserver;
import com.google.android.agera.MutableRepository;
import com.google.android.agera.UpdateDispatcher;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;


    repository2.accept(REPOSITORY_VALUE_B);
    runUiThreadTasksIncludingDelayedTasks();

    verify(mockPresenter1, never()).getItemCount(any());

    final int itemCount = repositoryAdapter.getItemCount();

    verify(mockPresenter2, never()).getItemCount(REPOSITORY_VALUE_A);
    verify(mockPresenter2).getItemCount(REPOSITORY_VALUE_B);
    assertThat(itemCount, is(
        PRESENTER_1_A_ITEM_COUNT + STATIC_ITEM_COUNT + PRESENTER_2_B_ITEM_COUNT));
    assertThat(repositoryAdapter.getItemId(PRESENTER_1_A_ITEM_COUNT + STATIC_ITEM_COUNT + 4),
        is(100L + STATIC_ITEM_COUNT));
    verify(mockPresenter2, never()).getUpdates(any(), any(), any(ListUpdateCallback.class));
  }

  @Test
  public void shouldApplyPresenter1ChangesWithEventsWhenObserved() {
    repositoryAdapter.getItemCount(); // usage
    when(mockPresenter1.getItemId(REPOSITORY_VALUE_B, 2)).thenReturn(10L);

    repository1.accept(REPOSITORY_VALUE_B);
    runUiThreadTasksIncludingDelayedTasks();

    assertThat(repositoryAdapter.getItemCount(), is(
        PRESENTER_1_B_ITEM_COUNT + STATIC_ITEM_COUNT + PRESENTER_2_A_ITEM_COUNT));
    assertThat(repositoryAdapter.getItemId(2), is(10L + STATIC_ITEM_COUNT));
    verify(mockPresenter1).getUpdates(eq(REPOSITORY_VALUE_A), eq(REPOSITORY_VALUE_B),
        any(ListUpdateCallback.class));
    applyPresenter1FromAToBChanges(verifyingWrapper(fineGrainedEvents));