diff options
| author | Samuel Tardieu <sam@rfc1149.net> | 2014-01-01 11:55:54 +0100 |
|---|---|---|
| committer | Samuel Tardieu <sam@rfc1149.net> | 2014-01-01 11:56:29 +0100 |
| commit | 08fde3648e575a7eead15bd830b4936451275e14 (patch) | |
| tree | bfa1b27cd7beb734aa40d95989d23f06fae1ced7 | |
| parent | 67fd44829a9704c618259db895d6fd4940d26b41 (diff) | |
| download | cgeo-08fde3648e575a7eead15bd830b4936451275e14.zip cgeo-08fde3648e575a7eead15bd830b4936451275e14.tar.gz cgeo-08fde3648e575a7eead15bd830b4936451275e14.tar.bz2 | |
fix #3500: crash with `null` completion in lazy lists
Also, add tests for `LazyInitializedList`.
| -rw-r--r-- | main/src/cgeo/geocaching/utils/LazyInitializedList.java | 8 | ||||
| -rw-r--r-- | tests/src/cgeo/geocaching/LazyInitialilzedListTest.java | 74 |
2 files changed, 82 insertions, 0 deletions
diff --git a/main/src/cgeo/geocaching/utils/LazyInitializedList.java b/main/src/cgeo/geocaching/utils/LazyInitializedList.java index 27649e8..e607919 100644 --- a/main/src/cgeo/geocaching/utils/LazyInitializedList.java +++ b/main/src/cgeo/geocaching/utils/LazyInitializedList.java @@ -1,7 +1,10 @@ package cgeo.geocaching.utils; +import org.eclipse.jdt.annotation.NonNull; + import java.util.AbstractList; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.concurrent.Callable; @@ -9,6 +12,7 @@ public abstract class LazyInitializedList<ElementType> extends AbstractList<Elem private volatile List<ElementType> list; + @NonNull private List<ElementType> getList() { if (list == null) { synchronized(this) { @@ -20,6 +24,10 @@ public abstract class LazyInitializedList<ElementType> extends AbstractList<Elem } catch (final Exception e) { Log.e("LazyInitializedList.getList", e); } + if (list == null) { + Log.e("LazyInitializedList.getList: using an empty list as a fallback"); + list = Collections.emptyList(); + } } } return list; diff --git a/tests/src/cgeo/geocaching/LazyInitialilzedListTest.java b/tests/src/cgeo/geocaching/LazyInitialilzedListTest.java new file mode 100644 index 0000000..bc4b6af --- /dev/null +++ b/tests/src/cgeo/geocaching/LazyInitialilzedListTest.java @@ -0,0 +1,74 @@ +package cgeo.geocaching; + +import cgeo.geocaching.utils.LazyInitializedList; + +import android.test.AndroidTestCase; + +import java.util.LinkedList; +import java.util.List; + +public class LazyInitialilzedListTest extends AndroidTestCase { + + private static final int MAKE_NULL = -1; + private static final int MAKE_EXCEPTION = -2; + + private static class MyList extends LazyInitializedList<Integer> { + + private int counter; + + MyList(int counter) { + this.counter = counter; + } + + @Override + public List<Integer> call() { + if (counter == MAKE_NULL) { + return null; + } + if (counter == MAKE_EXCEPTION) { + throw new RuntimeException("exception in call()"); + } + final List<Integer> result = new LinkedList<Integer>(); + for (int i = 0; i < counter; i++) { + result.add(counter); + } + counter += 1; + return result; + } + + int getCounter() { + return counter; + } + + } + + public static void testCallOnce() { + final MyList l = new MyList(0); + assertEquals("call() must not called prematurely", 0, l.getCounter()); + l.size(); + assertEquals("call() must be called when needed", 1, l.getCounter()); + l.size(); + assertEquals("call() must be called only once", 1, l.getCounter()); + } + + public static void testSize() { + final MyList l = new MyList(3); + assertEquals("completed size must be identical to call() result", 3, l.size()); + } + + public static void testValue() { + final MyList l = new MyList(1); + assertEquals("value must be identical to call() result", Integer.valueOf(1), l.get(0)); + } + + public static void testNull() { + final MyList l = new MyList(MAKE_NULL); + assertEquals("null returned by call() must create an empty list", 0, l.size()); + } + + public static void testException() { + final MyList l = new MyList(MAKE_EXCEPTION); + assertEquals("exception in call() must create an empty list", 0, l.size()); + } + +} |
