Commit 3ee2f2c8 authored by Jinsuk Kim's avatar Jinsuk Kim Committed by Commit Bot

Android: UserDataHost switches to throw RuntimeError

AssertionError-based tests are not guaranteed to work. This CL changes
the assertion exception used in UserDataHost class to runtime exceptions
to make it test-friendly. Items tested in the tests now throw
IllegalStateException or IllegalArgumentException.

Bug: 877918
Change-Id: I0f1d8c7d9b49a7b8c4020bdfaaf3e15479110b7d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1192484
Commit-Queue: Jinsuk Kim <jinsukkim@chromium.org>
Reviewed-by: default avatarRichard Coles <torne@chromium.org>
Cr-Commit-Position: refs/heads/master@{#708871}
parent d4365c02
...@@ -57,9 +57,20 @@ public final class UserDataHost { ...@@ -57,9 +57,20 @@ public final class UserDataHost {
private HashMap<Class<? extends UserData>, UserData> mUserDataMap = new HashMap<>(); private HashMap<Class<? extends UserData>, UserData> mUserDataMap = new HashMap<>();
private static void checkArgument(boolean condition) {
if (!condition) {
throw new IllegalArgumentException(
"Neither key nor object of UserDataHost can be null.");
}
}
private void checkThreadAndState() { private void checkThreadAndState() {
assert mThreadId == Process.myTid() : "UserData must only be used on a single thread."; if (mThreadId != Process.myTid()) {
assert mUserDataMap != null : "Operation is not allowed after destroy()"; throw new IllegalStateException("UserData must only be used on a single thread.");
}
if (mUserDataMap == null) {
throw new IllegalStateException("Operation is not allowed after destroy().");
}
} }
/** /**
...@@ -70,7 +81,7 @@ public final class UserDataHost { ...@@ -70,7 +81,7 @@ public final class UserDataHost {
*/ */
public <T extends UserData> T setUserData(Class<T> key, T object) { public <T extends UserData> T setUserData(Class<T> key, T object) {
checkThreadAndState(); checkThreadAndState();
assert key != null && object != null : "Neither key nor object of UserDataHost can be null"; checkArgument(key != null && object != null);
mUserDataMap.put(key, object); mUserDataMap.put(key, object);
return getUserData(key); return getUserData(key);
...@@ -85,22 +96,24 @@ public final class UserDataHost { ...@@ -85,22 +96,24 @@ public final class UserDataHost {
*/ */
public <T extends UserData> T getUserData(Class<T> key) { public <T extends UserData> T getUserData(Class<T> key) {
checkThreadAndState(); checkThreadAndState();
assert key != null : "UserDataHost key cannot be null"; checkArgument(key != null);
return key.cast(mUserDataMap.get(key)); return key.cast(mUserDataMap.get(key));
} }
/** /**
* Removes the mapping for a key from this map. Assertion will be thrown if * Removes the mapping for a key from this map. Exception will be thrown if
* the given key has no mapping. * the given key has no mapping.
* @param key Type token for which the specified object is to be removed. * @param key Type token for which the specified object is to be removed.
* @return The previous value associated with {@code key}. * @return The previous value associated with {@code key}.
*/ */
public <T extends UserData> T removeUserData(Class<T> key) { public <T extends UserData> T removeUserData(Class<T> key) {
checkThreadAndState(); checkThreadAndState();
assert key != null : "UserDataHost key cannot be null"; checkArgument(key != null);
assert mUserDataMap.containsKey(key) : "UserData for the key is not present"; if (!mUserDataMap.containsKey(key)) {
throw new IllegalStateException("UserData for the key is not present.");
}
return key.cast(mUserDataMap.remove(key)); return key.cast(mUserDataMap.remove(key));
} }
......
...@@ -11,7 +11,6 @@ import org.junit.Test; ...@@ -11,7 +11,6 @@ import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.DisabledTest;
/** /**
* Test class for {@link UserDataHost}. * Test class for {@link UserDataHost}.
...@@ -46,34 +45,31 @@ public class UserDataHostTest { ...@@ -46,34 +45,31 @@ public class UserDataHostTest {
} }
} }
private <T extends UserData> void assertGetUserData(Class<T> key) { private <T extends UserData, E extends RuntimeException> void getUserDataException(
boolean exception = false; Class<T> key, Class<E> exceptionType) {
try { try {
mHost.getUserData(key); mHost.getUserData(key);
} catch (AssertionError e) { } catch (Exception e) {
exception = true; if (!exceptionType.isInstance(e)) throw e;
} }
Assert.assertTrue(exception);
} }
private <T extends UserData> void assertSetUserData(Class<T> key, T obj) { private <T extends UserData, E extends RuntimeException> void setUserDataException(
boolean exception = false; Class<T> key, T obj, Class<E> exceptionType) {
try { try {
mHost.setUserData(key, obj); mHost.setUserData(key, obj);
} catch (AssertionError e) { } catch (Exception e) {
exception = true; if (!exceptionType.isInstance(e)) throw e;
} }
Assert.assertTrue(exception);
} }
private <T extends UserData> void assertRemoveUserData(Class<T> key) { private <T extends UserData, E extends RuntimeException> void removeUserDataException(
boolean exception = false; Class<T> key, Class<E> exceptionType) {
try { try {
mHost.removeUserData(key); mHost.removeUserData(key);
} catch (AssertionError e) { } catch (Exception e) {
exception = true; if (!exceptionType.isInstance(e)) throw e;
} }
Assert.assertTrue(exception);
} }
/** /**
...@@ -81,14 +77,13 @@ public class UserDataHostTest { ...@@ -81,14 +77,13 @@ public class UserDataHostTest {
*/ */
@Test @Test
@SmallTest @SmallTest
@DisabledTest
public void testBasicOperations() { public void testBasicOperations() {
TestObjectA obj = new TestObjectA(); TestObjectA obj = new TestObjectA();
mHost.setUserData(TestObjectA.class, obj); mHost.setUserData(TestObjectA.class, obj);
Assert.assertEquals(obj, mHost.getUserData(TestObjectA.class)); Assert.assertEquals(obj, mHost.getUserData(TestObjectA.class));
Assert.assertEquals(obj, mHost.removeUserData(TestObjectA.class)); Assert.assertEquals(obj, mHost.removeUserData(TestObjectA.class));
Assert.assertNull(mHost.getUserData(TestObjectA.class)); Assert.assertNull(mHost.getUserData(TestObjectA.class));
assertRemoveUserData(TestObjectA.class); removeUserDataException(TestObjectA.class, IllegalStateException.class);
} }
/** /**
...@@ -96,14 +91,13 @@ public class UserDataHostTest { ...@@ -96,14 +91,13 @@ public class UserDataHostTest {
*/ */
@Test @Test
@SmallTest @SmallTest
@DisabledTest
public void testNullKeyOrDataAreDisallowed() { public void testNullKeyOrDataAreDisallowed() {
TestObjectA obj = new TestObjectA(); TestObjectA obj = new TestObjectA();
assertSetUserData(null, null); setUserDataException(null, null, IllegalArgumentException.class);
assertSetUserData(TestObjectA.class, null); setUserDataException(TestObjectA.class, null, IllegalArgumentException.class);
assertSetUserData(null, obj); setUserDataException(null, obj, IllegalArgumentException.class);
assertGetUserData(null); getUserDataException(null, IllegalArgumentException.class);
assertRemoveUserData(null); removeUserDataException(null, IllegalArgumentException.class);
} }
/** /**
...@@ -121,6 +115,18 @@ public class UserDataHostTest { ...@@ -121,6 +115,18 @@ public class UserDataHostTest {
Assert.assertEquals(obj2, mHost.getUserData(TestObjectA.class)); Assert.assertEquals(obj2, mHost.getUserData(TestObjectA.class));
} }
/**
* Verifies operation on a different thread is not allowed.
*/
@Test
@SmallTest
public void testSingleThreadPolicy() {
TestObjectA obj = new TestObjectA();
mHost.setUserData(TestObjectA.class, obj);
ThreadUtils.runOnUiThreadBlocking(
() -> getUserDataException(TestObjectA.class, IllegalStateException.class));
}
/** /**
* Verifies {@link UserHostData#destroy()} detroyes each {@link UserData} object. * Verifies {@link UserHostData#destroy()} detroyes each {@link UserData} object.
*/ */
...@@ -144,15 +150,14 @@ public class UserDataHostTest { ...@@ -144,15 +150,14 @@ public class UserDataHostTest {
*/ */
@Test @Test
@SmallTest @SmallTest
@DisabledTest
public void testOperationsDisallowedAfterDestroy() { public void testOperationsDisallowedAfterDestroy() {
TestObjectA obj = new TestObjectA(); TestObjectA obj = new TestObjectA();
mHost.setUserData(TestObjectA.class, obj); mHost.setUserData(TestObjectA.class, obj);
Assert.assertEquals(obj, mHost.getUserData(TestObjectA.class)); Assert.assertEquals(obj, mHost.getUserData(TestObjectA.class));
mHost.destroy(); mHost.destroy();
assertGetUserData(TestObjectA.class); getUserDataException(TestObjectA.class, IllegalStateException.class);
assertSetUserData(TestObjectA.class, obj); setUserDataException(TestObjectA.class, obj, IllegalStateException.class);
assertRemoveUserData(TestObjectA.class); removeUserDataException(TestObjectA.class, IllegalStateException.class);
} }
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment