SimpleArrayMapTest.java revision a4f98193a1efa5a2de25451f59af4b91547974c2
1/* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15package android.support.v4.util; 16 17import static org.junit.Assert.fail; 18 19import android.support.test.filters.SmallTest; 20import android.support.test.runner.AndroidJUnit4; 21import android.util.Log; 22 23import org.junit.Test; 24import org.junit.runner.RunWith; 25 26import java.util.ConcurrentModificationException; 27 28/** 29 * Unit tests for SimpleArrayMap 30 */ 31@RunWith(AndroidJUnit4.class) 32@SmallTest 33public class SimpleArrayMapTest { 34 private static final String TAG = "SimpleArrayMapTest"; 35 SimpleArrayMap<String, String> map = new SimpleArrayMap<>(); 36 private boolean mDone; 37 38 /** 39 * Attempt to generate a ConcurrentModificationException in ArrayMap. 40 */ 41 @Test 42 public void testConcurrentModificationException() throws Exception { 43 final int TEST_LEN_MS = 5000; 44 Log.d(TAG, "Starting SimpleArrayMap concurrency test"); 45 mDone = false; 46 new Thread(new Runnable() { 47 @Override 48 public void run() { 49 int i = 0; 50 while (!mDone) { 51 try { 52 map.put(String.format("key %d", i++), "B_DONT_DO_THAT"); 53 } catch (ArrayIndexOutOfBoundsException e) { 54 // SimpleArrayMap is not thread safe, so lots of concurrent modifications 55 // can still cause data corruption 56 Log.w(TAG, "concurrent modification uncaught, causing indexing failure", e); 57 } catch (ClassCastException e) { 58 // cache corruption should not occur as it is hard to trace and one thread 59 // may corrupt the pool for all threads in the same process. 60 Log.e(TAG, "concurrent modification uncaught, causing cache corruption", e); 61 fail(); 62 } catch (ConcurrentModificationException e) { 63 } 64 } 65 } 66 }).start(); 67 for (int i = 0; i < (TEST_LEN_MS / 100); i++) { 68 try { 69 Thread.sleep(100); 70 map.clear(); 71 } catch (InterruptedException e) { 72 } catch (ArrayIndexOutOfBoundsException e) { 73 Log.w(TAG, "concurrent modification uncaught, causing indexing failure"); 74 } catch (ClassCastException e) { 75 Log.e(TAG, "concurrent modification uncaught, causing cache corruption"); 76 fail(); 77 } catch (ConcurrentModificationException e) { 78 } 79 } 80 mDone = true; 81 } 82 83 /** 84 * Check to make sure the same operations behave as expected in a single thread. 85 */ 86 @Test 87 public void testNonConcurrentAccesses() throws Exception { 88 for (int i = 0; i < 100000; i++) { 89 try { 90 map.put(String.format("key %d", i++), "B_DONT_DO_THAT"); 91 if (i % 500 == 0) { 92 map.clear(); 93 } 94 } catch (ConcurrentModificationException e) { 95 Log.e(TAG, "concurrent modification caught on single thread", e); 96 fail(); 97 } 98 } 99 } 100} 101