// Path: extensions/content/src/main/java/com/google/android/agera/content/ContentObservables.java
// @NonNull
// public static Observable broadcastObservable(@NonNull final Context context,
//     @NonNull final String... actions) {
//   return new BroadcastObservable(context, actions);
// }
// 
// Path: extensions/content/src/main/java/com/google/android/agera/content/ContentObservables.java
// @NonNull
// public static Observable sharedPreferencesObservable(@NonNull final SharedPreferences preferences,
//     @NonNull final String... keys) {
//   return new SharedPreferencesObservable(preferences, keys);
// }
// 
// Path: extensions/content/src/test/java/com/google/android/agera/content/test/mocks/MockUpdatable.java
// @NonNull
// public static MockUpdatable mockUpdatable() {
//   return new MockUpdatable();
// }
// 
// Path: agera/src/main/java/com/google/android/agera/ActivationHandler.java
// public interface ActivationHandler {
// 
//   /**
//    * Called when the the {@code caller} changes state from having no {@link Updatable}s to
//    * having at least one {@link Updatable}.
//    */
//   void observableActivated(@NonNull UpdateDispatcher caller);
// 
//   /**
//    * Called when the the {@code caller} changes state from having {@link Updatable}s to
//    * no longer having {@link Updatable}s.
//    */
//   void observableDeactivated(@NonNull UpdateDispatcher caller);
// }
// 
// Path: extensions/content/src/test/java/com/google/android/agera/content/test/mocks/MockUpdatable.java
// public final class MockUpdatable implements Updatable {
//   private final List<Observable> observables = new ArrayList<>();
// 
//   private boolean updated = false;
// 
//   private MockUpdatable() {}
// 
//   @NonNull
//   public static MockUpdatable mockUpdatable() {
//     return new MockUpdatable();
//   }
// 
//   @Override
//   public void update() {
//     updated = true;
//   }
// 
//   public boolean wasUpdated() {
//     runUiThreadTasksIncludingDelayedTasks();
//     return updated;
//   }
// 
//   public void resetUpdated() {
//     runUiThreadTasksIncludingDelayedTasks();
//     updated = false;
//   }
// 
//   public void addToObservable(@NonNull final Observable observable) {
//     observable.addUpdatable(this);
//     observables.add(observable);
//     runUiThreadTasksIncludingDelayedTasks();
//   }
// 
//   public void removeFromObservables() {
//     for (final Observable observable : observables) {
//       observable.removeUpdatable(this);
//     }
//     observables.clear();
//     runUiThreadTasksIncludingDelayedTasks();
//   }
// }


import static com.google.android.agera.content.ContentObservables.broadcastObservable;
import static com.google.android.agera.content.ContentObservables.sharedPreferencesObservable;
import static com.google.android.agera.content.test.matchers.HasPrivateConstructor.hasPrivateConstructor;
import static com.google.android.agera.content.test.matchers.UpdatableUpdated.wasUpdated;
import static com.google.android.agera.content.test.mocks.MockUpdatable.mockUpdatable;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.doNothing;
import static org.mockito.MockitoAnnotations.initMocks;
import static org.robolectric.annotation.Config.NONE;
import android.app.Application;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import com.google.android.agera.ActivationHandler;
import com.google.android.agera.content.test.matchers.UpdatableUpdated;
import com.google.android.agera.content.test.mocks.MockUpdatable;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
  }

  @After
  public void tearDown() {
    updatable.removeFromObservables();
    secondUpdatable.removeFromObservables();
  }

  @Test
  public void shouldUpdateSharedPreferencesWhenKeyChanges() {
    updatable.addToObservable(sharedPreferencesObservable(sharedPreferences, TEST_KEY));

    sharedPreferenceListenerCaptor.getValue()
        .onSharedPreferenceChanged(sharedPreferences, TEST_KEY);

    assertThat(updatable, wasUpdated());
  }

  @Test
  public void shouldNotUpdateSharedPreferencesWhenOtherKeyChanges() {
    updatable.addToObservable(sharedPreferencesObservable(sharedPreferences, TEST_KEY));

    sharedPreferenceListenerCaptor.getValue()
        .onSharedPreferenceChanged(sharedPreferences, NOT_TEST_KEY);

    assertThat(updatable, UpdatableUpdated.wasNotUpdated());
  }

  @Test
  public void shouldBeAbleToObserveBroadcasts() {
// Path: extensions/content/src/main/java/com/google/android/agera/content/ContentObservables.java
// @NonNull
// public static Observable broadcastObservable(@NonNull final Context context,
//     @NonNull final String... actions) {
//   return new BroadcastObservable(context, actions);
// }
// 
// Path: extensions/content/src/main/java/com/google/android/agera/content/ContentObservables.java
// @NonNull
// public static Observable sharedPreferencesObservable(@NonNull final SharedPreferences preferences,
//     @NonNull final String... keys) {
//   return new SharedPreferencesObservable(preferences, keys);
// }
// 
// Path: extensions/content/src/test/java/com/google/android/agera/content/test/mocks/MockUpdatable.java
// @NonNull
// public static MockUpdatable mockUpdatable() {
//   return new MockUpdatable();
// }
// 
// Path: agera/src/main/java/com/google/android/agera/ActivationHandler.java
// public interface ActivationHandler {
// 
//   /**
//    * Called when the the {@code caller} changes state from having no {@link Updatable}s to
//    * having at least one {@link Updatable}.
//    */
//   void observableActivated(@NonNull UpdateDispatcher caller);
// 
//   /**
//    * Called when the the {@code caller} changes state from having {@link Updatable}s to
//    * no longer having {@link Updatable}s.
//    */
//   void observableDeactivated(@NonNull UpdateDispatcher caller);
// }
// 
// Path: extensions/content/src/test/java/com/google/android/agera/content/test/mocks/MockUpdatable.java
// public final class MockUpdatable implements Updatable {
//   private final List<Observable> observables = new ArrayList<>();
// 
//   private boolean updated = false;
// 
//   private MockUpdatable() {}
// 
//   @NonNull
//   public static MockUpdatable mockUpdatable() {
//     return new MockUpdatable();
//   }
// 
//   @Override
//   public void update() {
//     updated = true;
//   }
// 
//   public boolean wasUpdated() {
//     runUiThreadTasksIncludingDelayedTasks();
//     return updated;
//   }
// 
//   public void resetUpdated() {
//     runUiThreadTasksIncludingDelayedTasks();
//     updated = false;
//   }
// 
//   public void addToObservable(@NonNull final Observable observable) {
//     observable.addUpdatable(this);
//     observables.add(observable);
//     runUiThreadTasksIncludingDelayedTasks();
//   }
// 
//   public void removeFromObservables() {
//     for (final Observable observable : observables) {
//       observable.removeUpdatable(this);
//     }
//     observables.clear();
//     runUiThreadTasksIncludingDelayedTasks();
//   }
// }


// Path: extensions/content/src/test/java/com/google/android/agera/content/ContentObservablesTest.java
import static com.google.android.agera.content.ContentObservables.broadcastObservable;
import static com.google.android.agera.content.ContentObservables.sharedPreferencesObservable;
import static com.google.android.agera.content.test.matchers.HasPrivateConstructor.hasPrivateConstructor;
import static com.google.android.agera.content.test.matchers.UpdatableUpdated.wasUpdated;
import static com.google.android.agera.content.test.mocks.MockUpdatable.mockUpdatable;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.doNothing;
import static org.mockito.MockitoAnnotations.initMocks;
import static org.robolectric.annotation.Config.NONE;
import android.app.Application;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import com.google.android.agera.ActivationHandler;
import com.google.android.agera.content.test.matchers.UpdatableUpdated;
import com.google.android.agera.content.test.mocks.MockUpdatable;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;

  }

  @After
  public void tearDown() {
    updatable.removeFromObservables();
    secondUpdatable.removeFromObservables();
  }

  @Test
  public void shouldUpdateSharedPreferencesWhenKeyChanges() {
    updatable.addToObservable(sharedPreferencesObservable(sharedPreferences, TEST_KEY));

    sharedPreferenceListenerCaptor.getValue()
        .onSharedPreferenceChanged(sharedPreferences, TEST_KEY);

    assertThat(updatable, wasUpdated());
  }

  @Test
  public void shouldNotUpdateSharedPreferencesWhenOtherKeyChanges() {
    updatable.addToObservable(sharedPreferencesObservable(sharedPreferences, TEST_KEY));

    sharedPreferenceListenerCaptor.getValue()
        .onSharedPreferenceChanged(sharedPreferences, NOT_TEST_KEY);

    assertThat(updatable, UpdatableUpdated.wasNotUpdated());
  }

  @Test
  public void shouldBeAbleToObserveBroadcasts() {
    updatable.addToObservable(broadcastObservable(getApplication(), TEST_ACTION));