blob: 5ff9e32db1cca45fa81e84306757e72da664e719 [file] [log] [blame]
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.collection;
import static org.junit.Assert.fail;
import org.junit.Test;
import java.util.ConcurrentModificationException;
import java.util.Locale;
/**
* Unit tests for SimpleArrayMap
*/
public class SimpleArrayMapTest {
SimpleArrayMap<String, String> map = new SimpleArrayMap<>();
private boolean mDone;
/**
* Attempt to generate a ConcurrentModificationException in ArrayMap.
*/
@Test
public void testConcurrentModificationException() throws Exception {
final int TEST_LEN_MS = 5000;
System.out.println("Starting SimpleArrayMap concurrency test");
mDone = false;
new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while (!mDone) {
try {
map.put(String.format(Locale.US, "key %d", i++), "B_DONT_DO_THAT");
} catch (ArrayIndexOutOfBoundsException e) {
// SimpleArrayMap is not thread safe, so lots of concurrent modifications
// can still cause data corruption
System.err.println("concurrent modification uncaught, causing indexing failure");
e.printStackTrace();
} catch (ClassCastException e) {
// cache corruption should not occur as it is hard to trace and one thread
// may corrupt the pool for all threads in the same process.
System.err.println("concurrent modification uncaught, causing cache corruption");
e.printStackTrace();
fail();
} catch (ConcurrentModificationException e) {
}
}
}
}).start();
for (int i = 0; i < (TEST_LEN_MS / 100); i++) {
try {
Thread.sleep(100);
map.clear();
} catch (InterruptedException e) {
} catch (ArrayIndexOutOfBoundsException e) {
System.err.println("concurrent modification uncaught, causing indexing failure");
} catch (ClassCastException e) {
System.err.println("concurrent modification uncaught, causing cache corruption");
fail();
} catch (ConcurrentModificationException e) {
}
}
mDone = true;
}
/**
* Check to make sure the same operations behave as expected in a single thread.
*/
@Test
public void testNonConcurrentAccesses() throws Exception {
for (int i = 0; i < 100000; i++) {
try {
map.put(String.format(Locale.US, "key %d", i++), "B_DONT_DO_THAT");
if (i % 500 == 0) {
map.clear();
}
} catch (ConcurrentModificationException e) {
System.err.println("Concurrent modification caught on single thread");
e.printStackTrace();
fail();
}
}
}
}