Home | History | Annotate | Download | only in collection
      1 /*
      2  * Copyright 2018 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 
     17 package androidx.collection;
     18 
     19 import static org.junit.Assert.fail;
     20 
     21 import org.junit.Test;
     22 
     23 import java.util.ConcurrentModificationException;
     24 import java.util.Locale;
     25 
     26 /**
     27  * Unit tests for SimpleArrayMap
     28  */
     29 public class SimpleArrayMapTest {
     30     SimpleArrayMap<String, String> map = new SimpleArrayMap<>();
     31     private boolean mDone;
     32 
     33     /**
     34      * Attempt to generate a ConcurrentModificationException in ArrayMap.
     35      */
     36     @Test
     37     public void testConcurrentModificationException() throws Exception {
     38         final int TEST_LEN_MS = 5000;
     39         System.out.println("Starting SimpleArrayMap concurrency test");
     40         mDone = false;
     41         new Thread(new Runnable() {
     42             @Override
     43             public void run() {
     44                 int i = 0;
     45                 while (!mDone) {
     46                     try {
     47                         map.put(String.format(Locale.US, "key %d", i++), "B_DONT_DO_THAT");
     48                     } catch (ArrayIndexOutOfBoundsException e) {
     49                         // SimpleArrayMap is not thread safe, so lots of concurrent modifications
     50                         // can still cause data corruption
     51                         System.err.println("concurrent modification uncaught, causing indexing failure");
     52                         e.printStackTrace();
     53                     } catch (ClassCastException e) {
     54                         // cache corruption should not occur as it is hard to trace and one thread
     55                         // may corrupt the pool for all threads in the same process.
     56                         System.err.println("concurrent modification uncaught, causing cache corruption");
     57                         e.printStackTrace();
     58                         fail();
     59                     } catch (ConcurrentModificationException e) {
     60                     }
     61                 }
     62             }
     63         }).start();
     64         for (int i = 0; i < (TEST_LEN_MS / 100); i++) {
     65             try {
     66                 Thread.sleep(100);
     67                 map.clear();
     68             } catch (InterruptedException e) {
     69             } catch (ArrayIndexOutOfBoundsException e) {
     70                 System.err.println("concurrent modification uncaught, causing indexing failure");
     71             } catch (ClassCastException e) {
     72                 System.err.println("concurrent modification uncaught, causing cache corruption");
     73                 fail();
     74             } catch (ConcurrentModificationException e) {
     75             }
     76         }
     77         mDone = true;
     78     }
     79 
     80     /**
     81      * Check to make sure the same operations behave as expected in a single thread.
     82      */
     83     @Test
     84     public void testNonConcurrentAccesses() throws Exception {
     85         for (int i = 0; i < 100000; i++) {
     86             try {
     87                 map.put(String.format(Locale.US, "key %d", i++), "B_DONT_DO_THAT");
     88                 if (i % 500 == 0) {
     89                     map.clear();
     90                 }
     91             } catch (ConcurrentModificationException e) {
     92                 System.err.println("Concurrent modification caught on single thread");
     93                 e.printStackTrace();
     94                 fail();
     95             }
     96         }
     97     }
     98 }
     99