1 // Copyright 2020 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.base.supplier; 6 7 import org.junit.After; 8 import org.junit.Assert; 9 import org.junit.Before; 10 import org.junit.Test; 11 import org.junit.runner.RunWith; 12 import org.mockito.Mockito; 13 import org.robolectric.annotation.Config; 14 15 import org.chromium.base.Callback; 16 import org.chromium.base.UnownedUserDataHost; 17 import org.chromium.base.UnownedUserDataKey; 18 import org.chromium.base.test.BaseRobolectricTestRunner; 19 20 /** Unit tests for {@link ObservableSupplierImpl}. */ 21 @RunWith(BaseRobolectricTestRunner.class) 22 @Config(manifest = Config.NONE) 23 public class UnownedUserDataSupplierTest { 24 /** Serves as an example concrete class for {@link UnownedUserDataSupplier}. */ 25 static class TestUnownedUserDataSupplier extends UnownedUserDataSupplier<String> { 26 private static final UnownedUserDataKey<TestUnownedUserDataSupplier> KEY = 27 new UnownedUserDataKey<TestUnownedUserDataSupplier>( 28 TestUnownedUserDataSupplier.class); 29 30 /** Use this pattern to mock the {@link UnownedUserDataSupplier} for testing. */ 31 private static TestUnownedUserDataSupplier sInstanceForTesting; 32 33 /** 34 * Retrieves an {@link ObservableSupplier} from the given host. Real implementations should 35 * use {@link WindowAndroid}. 36 */ from(UnownedUserDataHost host)37 public static ObservableSupplier<String> from(UnownedUserDataHost host) { 38 if (sInstanceForTesting != null) return sInstanceForTesting; 39 return KEY.retrieveDataFromHost(host); 40 } 41 42 /** 43 * Constructs a {@link TestUnownedUserDataSupplier} with the given host. Real 44 * implementations should use {@link WindowAndroid} instead. 45 */ TestUnownedUserDataSupplier()46 public TestUnownedUserDataSupplier() { 47 super(KEY); 48 } 49 getUnownedUserDataKeyForTesting()50 static UnownedUserDataKey<TestUnownedUserDataSupplier> getUnownedUserDataKeyForTesting() { 51 return KEY; 52 } 53 setInstanceForTesting(TestUnownedUserDataSupplier testUnownedUserDataSupplier)54 static void setInstanceForTesting(TestUnownedUserDataSupplier testUnownedUserDataSupplier) { 55 sInstanceForTesting = testUnownedUserDataSupplier; 56 } 57 } 58 59 static final String TEST_STRING_1 = "testString1"; 60 static final String TEST_STRING_2 = "testString2"; 61 62 private final UnownedUserDataHost mHost = new UnownedUserDataHost(); 63 private final TestUnownedUserDataSupplier mSupplier = new TestUnownedUserDataSupplier(); 64 65 private boolean mIsDestroyed; 66 67 @Before setUp()68 public void setUp() { 69 mIsDestroyed = false; 70 mSupplier.attach(mHost); 71 } 72 73 @After tearDown()74 public void tearDown() { 75 if (!mIsDestroyed) { 76 mSupplier.destroy(); 77 mIsDestroyed = true; 78 } 79 80 Assert.assertNull(TestUnownedUserDataSupplier.from(mHost)); 81 } 82 83 @Test testSet()84 public void testSet() { 85 mSupplier.set(TEST_STRING_1); 86 87 // Simulate client 88 ObservableSupplierImpl<String> supplier = 89 (ObservableSupplierImpl) TestUnownedUserDataSupplier.from(mHost); 90 Assert.assertEquals(TEST_STRING_1, supplier.get()); 91 92 Callback<String> callback = Mockito.mock(Callback.class); 93 supplier.addObserver(callback); 94 supplier.set(TEST_STRING_2); 95 Mockito.verify(callback).onResult(TEST_STRING_2); 96 } 97 98 @Test testAttachMultipleSuppliersToSameHost()99 public void testAttachMultipleSuppliersToSameHost() { 100 TestUnownedUserDataSupplier secondarySupplier = new TestUnownedUserDataSupplier(); 101 secondarySupplier.attach(mHost); 102 Assert.assertFalse( 103 TestUnownedUserDataSupplier.getUnownedUserDataKeyForTesting() 104 .isAttachedToAnyHost(mSupplier)); 105 Assert.assertTrue( 106 TestUnownedUserDataSupplier.getUnownedUserDataKeyForTesting() 107 .isAttachedToAnyHost(secondarySupplier)); 108 secondarySupplier.destroy(); 109 } 110 111 @Test testAttachSupplierToMultipleHosts()112 public void testAttachSupplierToMultipleHosts() { 113 UnownedUserDataHost secondaryHost = new UnownedUserDataHost(); 114 mSupplier.attach(secondaryHost); 115 Assert.assertTrue( 116 TestUnownedUserDataSupplier.getUnownedUserDataKeyForTesting() 117 .isAttachedToAnyHost(mSupplier)); 118 mSupplier.destroy(); 119 mIsDestroyed = true; 120 Assert.assertFalse( 121 TestUnownedUserDataSupplier.getUnownedUserDataKeyForTesting() 122 .isAttachedToAnyHost(mSupplier)); 123 } 124 125 @Test testDestroy()126 public void testDestroy() { 127 Assert.assertTrue( 128 TestUnownedUserDataSupplier.getUnownedUserDataKeyForTesting() 129 .isAttachedToAnyHost(mSupplier)); 130 131 mSupplier.destroy(); 132 Assert.assertNull(TestUnownedUserDataSupplier.from(mHost)); 133 Assert.assertFalse( 134 TestUnownedUserDataSupplier.getUnownedUserDataKeyForTesting() 135 .isAttachedToAnyHost(mSupplier)); 136 mIsDestroyed = true; 137 } 138 139 @Test testDestroy_unattached()140 public void testDestroy_unattached() { 141 // Destroy the primary supplier that's attached automatically. 142 mSupplier.destroy(); 143 144 TestUnownedUserDataSupplier secondarySupplier = new TestUnownedUserDataSupplier(); 145 Assert.assertFalse( 146 TestUnownedUserDataSupplier.getUnownedUserDataKeyForTesting() 147 .isAttachedToHost(mHost)); 148 149 secondarySupplier.destroy(); 150 Assert.assertFalse( 151 TestUnownedUserDataSupplier.getUnownedUserDataKeyForTesting() 152 .isAttachedToHost(mHost)); 153 mIsDestroyed = true; 154 } 155 156 @Test testDestroy_DoubleDestroy()157 public void testDestroy_DoubleDestroy() { 158 mSupplier.destroy(); 159 try { 160 mSupplier.destroy(); 161 throw new Error("Expected an assert to be triggered."); 162 } catch (AssertionError e) { 163 } 164 mIsDestroyed = true; 165 } 166 } 167