1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.settingslib.core.lifecycle; 17 18 import static android.arch.lifecycle.Lifecycle.Event.ON_START; 19 import static com.google.common.truth.Truth.assertThat; 20 21 import android.arch.lifecycle.LifecycleOwner; 22 import android.content.Context; 23 import android.view.Menu; 24 import android.view.MenuInflater; 25 import android.view.MenuItem; 26 27 import com.android.settingslib.SettingsLibRobolectricTestRunner; 28 import com.android.settingslib.core.lifecycle.events.OnAttach; 29 import com.android.settingslib.core.lifecycle.events.OnCreateOptionsMenu; 30 import com.android.settingslib.core.lifecycle.events.OnDestroy; 31 import com.android.settingslib.core.lifecycle.events.OnOptionsItemSelected; 32 import com.android.settingslib.core.lifecycle.events.OnPause; 33 import com.android.settingslib.core.lifecycle.events.OnPrepareOptionsMenu; 34 import com.android.settingslib.core.lifecycle.events.OnResume; 35 import com.android.settingslib.core.lifecycle.events.OnStart; 36 import com.android.settingslib.core.lifecycle.events.OnStop; 37 38 import org.junit.Before; 39 import org.junit.Test; 40 import org.junit.runner.RunWith; 41 import org.robolectric.Robolectric; 42 import org.robolectric.android.controller.ActivityController; 43 import org.robolectric.android.controller.FragmentController; 44 45 @RunWith(SettingsLibRobolectricTestRunner.class) 46 public class LifecycleTest { 47 48 private LifecycleOwner mLifecycleOwner; 49 private Lifecycle mLifecycle; 50 51 public static class TestDialogFragment extends ObservableDialogFragment { 52 53 final TestObserver mFragObserver; 54 55 public TestDialogFragment() { 56 mFragObserver = new TestObserver(); 57 mLifecycle.addObserver(mFragObserver); 58 } 59 } 60 61 public static class TestFragment extends ObservableFragment { 62 63 final TestObserver mFragObserver; 64 65 public TestFragment() { 66 mFragObserver = new TestObserver(); 67 getLifecycle().addObserver(mFragObserver); 68 } 69 } 70 71 public static class TestActivity extends ObservableActivity { 72 73 final TestObserver mActObserver; 74 75 public TestActivity() { 76 mActObserver = new TestObserver(); 77 getLifecycle().addObserver(mActObserver); 78 } 79 80 } 81 82 public static class TestObserver implements LifecycleObserver, OnAttach, OnStart, OnResume, 83 OnPause, OnStop, OnDestroy, OnCreateOptionsMenu, OnPrepareOptionsMenu, 84 OnOptionsItemSelected { 85 86 boolean mOnAttachObserved; 87 boolean mOnAttachHasContext; 88 boolean mOnStartObserved; 89 boolean mOnResumeObserved; 90 boolean mOnPauseObserved; 91 boolean mOnStopObserved; 92 boolean mOnDestroyObserved; 93 boolean mOnCreateOptionsMenuObserved; 94 boolean mOnPrepareOptionsMenuObserved; 95 boolean mOnOptionsItemSelectedObserved; 96 97 @Override 98 public void onAttach(Context context) { 99 mOnAttachObserved = true; 100 mOnAttachHasContext = context != null; 101 } 102 103 @Override 104 public void onStart() { 105 mOnStartObserved = true; 106 } 107 108 @Override 109 public void onPause() { 110 mOnPauseObserved = true; 111 } 112 113 @Override 114 public void onResume() { 115 mOnResumeObserved = true; 116 } 117 118 @Override 119 public void onStop() { 120 mOnStopObserved = true; 121 } 122 123 @Override 124 public void onDestroy() { 125 mOnDestroyObserved = true; 126 } 127 128 @Override 129 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 130 mOnCreateOptionsMenuObserved = true; 131 } 132 133 @Override 134 public boolean onOptionsItemSelected(MenuItem menuItem) { 135 mOnOptionsItemSelectedObserved = true; 136 return true; 137 } 138 139 @Override 140 public void onPrepareOptionsMenu(Menu menu) { 141 mOnPrepareOptionsMenuObserved = true; 142 } 143 } 144 145 @Before 146 public void setUp() { 147 mLifecycleOwner = () -> mLifecycle; 148 mLifecycle = new Lifecycle(mLifecycleOwner); 149 } 150 151 @Test 152 public void runThroughActivityLifecycles_shouldObserveEverything() { 153 ActivityController<TestActivity> ac = Robolectric.buildActivity(TestActivity.class); 154 TestActivity activity = ac.get(); 155 156 ac.start(); 157 assertThat(activity.mActObserver.mOnStartObserved).isTrue(); 158 ac.resume(); 159 assertThat(activity.mActObserver.mOnResumeObserved).isTrue(); 160 activity.onCreateOptionsMenu(null); 161 assertThat(activity.mActObserver.mOnCreateOptionsMenuObserved).isTrue(); 162 activity.onPrepareOptionsMenu(null); 163 assertThat(activity.mActObserver.mOnPrepareOptionsMenuObserved).isTrue(); 164 activity.onOptionsItemSelected(null); 165 assertThat(activity.mActObserver.mOnOptionsItemSelectedObserved).isTrue(); 166 ac.pause(); 167 assertThat(activity.mActObserver.mOnPauseObserved).isTrue(); 168 ac.stop(); 169 assertThat(activity.mActObserver.mOnStopObserved).isTrue(); 170 ac.destroy(); 171 assertThat(activity.mActObserver.mOnDestroyObserved).isTrue(); 172 } 173 174 @Test 175 public void runThroughDialogFragmentLifecycles_shouldObserveEverything() { 176 FragmentController<TestDialogFragment> fragmentController = 177 Robolectric.buildFragment(TestDialogFragment.class); 178 TestDialogFragment fragment = fragmentController.get(); 179 180 fragmentController.create().start().resume(); 181 fragment.onCreateOptionsMenu(null, null); 182 fragment.onPrepareOptionsMenu(null); 183 fragment.onOptionsItemSelected(null); 184 fragmentController.pause().stop().destroy(); 185 186 assertThat(fragment.mFragObserver.mOnAttachObserved).isTrue(); 187 assertThat(fragment.mFragObserver.mOnAttachHasContext).isTrue(); 188 assertThat(fragment.mFragObserver.mOnStartObserved).isTrue(); 189 assertThat(fragment.mFragObserver.mOnResumeObserved).isTrue(); 190 assertThat(fragment.mFragObserver.mOnPauseObserved).isTrue(); 191 assertThat(fragment.mFragObserver.mOnStopObserved).isTrue(); 192 assertThat(fragment.mFragObserver.mOnDestroyObserved).isTrue(); 193 assertThat(fragment.mFragObserver.mOnCreateOptionsMenuObserved).isTrue(); 194 assertThat(fragment.mFragObserver.mOnPrepareOptionsMenuObserved).isTrue(); 195 assertThat(fragment.mFragObserver.mOnOptionsItemSelectedObserved).isTrue(); 196 } 197 198 @Test 199 public void runThroughFragmentLifecycles_shouldObserveEverything() { 200 FragmentController<TestFragment> fragmentController = 201 Robolectric.buildFragment(TestFragment.class); 202 TestFragment fragment = fragmentController.get(); 203 204 fragmentController.create().start().resume(); 205 fragment.onCreateOptionsMenu(null, null); 206 fragment.onPrepareOptionsMenu(null); 207 fragment.onOptionsItemSelected(null); 208 fragmentController.pause().stop().destroy(); 209 210 assertThat(fragment.mFragObserver.mOnAttachObserved).isTrue(); 211 assertThat(fragment.mFragObserver.mOnAttachHasContext).isTrue(); 212 assertThat(fragment.mFragObserver.mOnStartObserved).isTrue(); 213 assertThat(fragment.mFragObserver.mOnResumeObserved).isTrue(); 214 assertThat(fragment.mFragObserver.mOnPauseObserved).isTrue(); 215 assertThat(fragment.mFragObserver.mOnStopObserved).isTrue(); 216 assertThat(fragment.mFragObserver.mOnDestroyObserved).isTrue(); 217 assertThat(fragment.mFragObserver.mOnCreateOptionsMenuObserved).isTrue(); 218 assertThat(fragment.mFragObserver.mOnPrepareOptionsMenuObserved).isTrue(); 219 assertThat(fragment.mFragObserver.mOnOptionsItemSelectedObserved).isTrue(); 220 } 221 222 @Test 223 public void addObserverDuringObserve_shoudNotCrash() { 224 mLifecycle.addObserver(new OnStartObserver(mLifecycle)); 225 mLifecycle.handleLifecycleEvent(ON_START); 226 } 227 228 private static class OptionItemAccepter implements LifecycleObserver, OnOptionsItemSelected { 229 public boolean wasCalled = false; 230 231 @Override 232 public boolean onOptionsItemSelected(MenuItem menuItem) { 233 wasCalled = true; 234 return false; 235 } 236 } 237 238 @Test 239 public void onOptionItemSelectedShortCircuitsIfAnObserverHandlesTheMenuItem() { 240 FragmentController<TestFragment> fragmentController = 241 Robolectric.buildFragment(TestFragment.class); 242 TestFragment fragment = fragmentController.get(); 243 OptionItemAccepter accepter = new OptionItemAccepter(); 244 fragment.getLifecycle().addObserver(accepter); 245 246 fragmentController.create().start().resume(); 247 fragment.onCreateOptionsMenu(null, null); 248 fragment.onPrepareOptionsMenu(null); 249 fragment.onOptionsItemSelected(null); 250 fragmentController.pause().stop().destroy(); 251 252 assertThat(accepter.wasCalled).isFalse(); 253 } 254 255 private class OnStartObserver implements LifecycleObserver, OnStart { 256 257 private final Lifecycle mLifecycle; 258 259 public OnStartObserver(Lifecycle lifecycle) { 260 mLifecycle = lifecycle; 261 } 262 263 @Override 264 public void onStart() { 265 mLifecycle.addObserver(new LifecycleObserver() { 266 }); 267 } 268 } 269 } 270