blob: 98040a00603325ed3ef56e6c3cb69970d3642bbf [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.logging.log4j.util;
import org.junit.jupiter.api.Test;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
/**
* Tests the SortedArrayStringMap class.
*/
public class SortedArrayStringMapTest {
@Test
public void testConstructorDisallowsNegativeCapacity() {
assertThrows(IllegalArgumentException.class, () -> new SortedArrayStringMap(-1));
}
@Test
public void testConstructorAllowsZeroCapacity() {
SortedArrayStringMap sortedArrayStringMap = new SortedArrayStringMap(0);
assertEquals(0, sortedArrayStringMap.size());
}
@Test
public void testConstructorIgnoresNull() {
assertEquals(0, new SortedArrayStringMap((SortedArrayStringMap) null).size());
}
@Test
public void testToString() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("B", "Bvalue");
original.putValue("3", "3value");
assertEquals("{3=3value, B=Bvalue, a=avalue}", original.toString());
}
@Test
public void testSerialization() throws Exception {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("B", "Bvalue");
original.putValue("3", "3value");
final byte[] binary = serialize(original);
final SortedArrayStringMap copy = deserialize(binary);
assertEquals(original, copy);
}
@Test
public void testSerializationOfNonSerializableValue() throws Exception {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("B", "Bvalue");
original.putValue("unserializable", new Object());
final byte[] binary = serialize(original);
final SortedArrayStringMap copy = deserialize(binary);
final SortedArrayStringMap expected = new SortedArrayStringMap();
expected.putValue("a", "avalue");
expected.putValue("B", "Bvalue");
expected.putValue("unserializable", null);
assertEquals(expected, copy);
}
@Test
public void testDeserializationOfUnknownClass() throws Exception {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("serializableButNotInClasspathOfDeserializer", new org.junit.runner.Result());
original.putValue("zz", "last");
final File file = new File("target/SortedArrayStringMap.ser");
try (FileOutputStream fout = new FileOutputStream(file, false)) {
fout.write(serialize(original));
fout.flush();
}
final String classpath = createClassPath(SortedArrayStringMap.class, DeserializerHelper.class);
final Process process = new ProcessBuilder("java", "-cp", classpath,
DeserializerHelper.class.getName(), file.getPath()).start();
final BufferedReader in = new BufferedReader(new InputStreamReader(process.getErrorStream()));
final int exitValue = process.waitFor();
file.delete();
if (exitValue != 0) {
final StringBuilder sb = new StringBuilder();
sb.append("DeserializerHelper exited with error code ").append(exitValue);
sb.append(". Classpath='").append(classpath);
sb.append("'. Process output: ");
int c = -1;
while ((c = in.read()) != -1) {
sb.append((char) c);
}
fail(sb.toString());
}
}
private String createClassPath(final Class<?>... classes) throws Exception {
final StringBuilder result = new StringBuilder();
for (final Class<?> cls : classes) {
if (result.length() > 0) {
result.append(File.pathSeparator);
}
result.append(createClassPath(cls));
}
return result.toString();
}
private String createClassPath(final Class<?> cls) throws Exception {
final String resource = "/" + cls.getName().replace('.', '/') + ".class";
final URL url = cls.getResource(resource);
String location = url.toString();
if (location.startsWith("jar:")) {
location = location.substring("jar:".length(), location.indexOf('!'));
}
if (location.startsWith("file:/")) {
location = location.substring("file:/".length());
}
if (location.endsWith(resource)) {
location = location.substring(0, location.length() - resource.length());
}
if (!new File(location).exists()) {
location = File.separator + location;
}
location = URLDecoder.decode(location, Charset.defaultCharset().name()); // replace %20 with ' ' etc
return location.isEmpty() ? "." : location;
}
private byte[] serialize(final SortedArrayStringMap data) throws IOException {
final ByteArrayOutputStream arr = new ByteArrayOutputStream();
final ObjectOutputStream out = new ObjectOutputStream(arr);
out.writeObject(data);
return arr.toByteArray();
}
@SuppressWarnings("BanSerializableRead")
private SortedArrayStringMap deserialize(final byte[] binary) throws IOException, ClassNotFoundException {
final ByteArrayInputStream inArr = new ByteArrayInputStream(binary);
try (final ObjectInputStream in = new FilteredObjectInputStream(inArr)) {
final SortedArrayStringMap result = (SortedArrayStringMap) in.readObject();
return result;
}
}
@Test
public void testPutAll() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("B", "Bvalue");
original.putValue("3", "3value");
final SortedArrayStringMap other = new SortedArrayStringMap();
other.putAll(original);
assertEquals(original, other);
other.putValue("3", "otherValue");
assertNotEquals(original, other);
other.putValue("3", null);
assertNotEquals(original, other);
other.putValue("3", "3value");
assertEquals(original, other);
}
@Test
public void testPutAll_overwritesSameKeys2() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "aORIG");
original.putValue("b", "bORIG");
original.putValue("c", "cORIG");
original.putValue("d", "dORIG");
original.putValue("e", "eORIG");
final SortedArrayStringMap other = new SortedArrayStringMap();
other.putValue("1", "11");
other.putValue("2", "22");
other.putValue("a", "aa");
other.putValue("c", "cc");
original.putAll(other);
assertEquals(7, original.size(), "size after put other");
assertEquals("aa", original.getValue("a"));
assertEquals("bORIG", original.getValue("b"));
assertEquals("cc", original.getValue("c"));
assertEquals("dORIG", original.getValue("d"));
assertEquals("eORIG", original.getValue("e"));
assertEquals("11", original.getValue("1"));
assertEquals("22", original.getValue("2"));
}
@Test
public void testPutAll_nullKeyInLargeOriginal() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue(null, "nullORIG");
original.putValue("a", "aORIG");
original.putValue("b", "bORIG");
original.putValue("c", "cORIG");
original.putValue("d", "dORIG");
original.putValue("e", "eORIG");
final SortedArrayStringMap other = new SortedArrayStringMap();
other.putValue("1", "11");
other.putValue("a", "aa");
original.putAll(other);
assertEquals(7, original.size(), "size after put other");
assertEquals("aa", original.getValue("a"));
assertEquals("bORIG", original.getValue("b"));
assertEquals("cORIG", original.getValue("c"));
assertEquals("dORIG", original.getValue("d"));
assertEquals("eORIG", original.getValue("e"));
assertEquals("11", original.getValue("1"));
assertEquals("nullORIG", original.getValue(null));
}
@Test
public void testPutAll_nullKeyInSmallOriginal() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue(null, "nullORIG");
original.putValue("a", "aORIG");
original.putValue("b", "bORIG");
final SortedArrayStringMap other = new SortedArrayStringMap();
other.putValue("1", "11");
other.putValue("2", "22");
other.putValue("3", "33");
other.putValue("a", "aa");
original.putAll(other);
assertEquals(6, original.size(), "size after put other");
assertEquals("aa", original.getValue("a"));
assertEquals("bORIG", original.getValue("b"));
assertEquals("11", original.getValue("1"));
assertEquals("22", original.getValue("2"));
assertEquals("33", original.getValue("3"));
assertEquals("nullORIG", original.getValue(null));
}
@Test
public void testPutAll_nullKeyInSmallAdditional() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "aORIG");
original.putValue("b", "bORIG");
original.putValue("c", "cORIG");
original.putValue("d", "dORIG");
original.putValue("e", "eORIG");
final SortedArrayStringMap other = new SortedArrayStringMap();
other.putValue(null, "nullNEW");
other.putValue("1", "11");
other.putValue("a", "aa");
original.putAll(other);
assertEquals(7, original.size(), "size after put other");
assertEquals("aa", original.getValue("a"));
assertEquals("bORIG", original.getValue("b"));
assertEquals("cORIG", original.getValue("c"));
assertEquals("dORIG", original.getValue("d"));
assertEquals("eORIG", original.getValue("e"));
assertEquals("11", original.getValue("1"));
assertEquals("nullNEW", original.getValue(null));
}
@Test
public void testPutAll_nullKeyInLargeAdditional() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "aORIG");
original.putValue("b", "bORIG");
final SortedArrayStringMap other = new SortedArrayStringMap();
other.putValue(null, "nullNEW");
other.putValue("1", "11");
other.putValue("2", "22");
other.putValue("3", "33");
other.putValue("a", "aa");
original.putAll(other);
assertEquals(6, original.size(), "size after put other");
assertEquals("aa", original.getValue("a"));
assertEquals("bORIG", original.getValue("b"));
assertEquals("11", original.getValue("1"));
assertEquals("22", original.getValue("2"));
assertEquals("33", original.getValue("3"));
assertEquals("nullNEW", original.getValue(null));
}
@Test
public void testPutAll_nullKeyInBoth_LargeOriginal() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue(null, "nullORIG");
original.putValue("a", "aORIG");
original.putValue("b", "bORIG");
original.putValue("c", "cORIG");
original.putValue("d", "dORIG");
original.putValue("e", "eORIG");
final SortedArrayStringMap other = new SortedArrayStringMap();
other.putValue(null, "nullNEW");
other.putValue("1", "11");
other.putValue("a", "aa");
original.putAll(other);
assertEquals(7, original.size(), "size after put other");
assertEquals("aa", original.getValue("a"));
assertEquals("bORIG", original.getValue("b"));
assertEquals("cORIG", original.getValue("c"));
assertEquals("dORIG", original.getValue("d"));
assertEquals("eORIG", original.getValue("e"));
assertEquals("11", original.getValue("1"));
assertEquals("nullNEW", original.getValue(null));
}
@Test
public void testPutAll_nullKeyInBoth_SmallOriginal() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue(null, "nullORIG");
original.putValue("a", "aORIG");
original.putValue("b", "bORIG");
final SortedArrayStringMap other = new SortedArrayStringMap();
other.putValue(null, "nullNEW");
other.putValue("1", "11");
other.putValue("2", "22");
other.putValue("3", "33");
other.putValue("a", "aa");
original.putAll(other);
assertEquals(6, original.size(), "size after put other");
assertEquals("aa", original.getValue("a"));
assertEquals("bORIG", original.getValue("b"));
assertEquals("11", original.getValue("1"));
assertEquals("22", original.getValue("2"));
assertEquals("33", original.getValue("3"));
assertEquals("nullNEW", original.getValue(null));
}
@Test
public void testPutAll_overwritesSameKeys1() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "aORIG");
original.putValue("b", "bORIG");
original.putValue("c", "cORIG");
final SortedArrayStringMap other = new SortedArrayStringMap();
other.putValue("1", "11");
other.putValue("2", "22");
other.putValue("a", "aa");
other.putValue("c", "cc");
original.putAll(other);
assertEquals(5, original.size(), "size after put other");
assertEquals("aa", original.getValue("a"));
assertEquals("bORIG", original.getValue("b"));
assertEquals("cc", original.getValue("c"));
assertEquals("11", original.getValue("1"));
assertEquals("22", original.getValue("2"));
}
@Test
public void testEquals() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("B", "Bvalue");
original.putValue("3", "3value");
assertEquals(original, original); // equal to itself
final SortedArrayStringMap other = new SortedArrayStringMap();
other.putValue("a", "avalue");
assertNotEquals(original, other);
other.putValue("B", "Bvalue");
assertNotEquals(original, other);
other.putValue("3", "3value");
assertEquals(original, other);
other.putValue("3", "otherValue");
assertNotEquals(original, other);
other.putValue("3", null);
assertNotEquals(original, other);
other.putValue("3", "3value");
assertEquals(original, other);
}
@Test
public void testToMap() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("B", "Bvalue");
original.putValue("3", "3value");
final Map<String, Object> expected = new HashMap<>();
expected.put("a", "avalue");
expected.put("B", "Bvalue");
expected.put("3", "3value");
assertEquals(expected, original.toMap());
assertDoesNotThrow(() -> original.toMap().put("abc", "xyz"), "Expected map to be mutable");
}
@Test
public void testPutAll_KeepsExistingValues() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "aaa");
original.putValue("b", "bbb");
original.putValue("c", "ccc");
assertEquals(3, original.size(), "size");
// add empty context data
original.putAll(new SortedArrayStringMap());
assertEquals(3, original.size(), "size after put empty");
assertEquals("aaa", original.getValue("a"));
assertEquals("bbb", original.getValue("b"));
assertEquals("ccc", original.getValue("c"));
final SortedArrayStringMap other = new SortedArrayStringMap();
other.putValue("1", "111");
other.putValue("2", "222");
other.putValue("3", "333");
original.putAll(other);
assertEquals(6, original.size(), "size after put other");
assertEquals("aaa", original.getValue("a"));
assertEquals("bbb", original.getValue("b"));
assertEquals("ccc", original.getValue("c"));
assertEquals("111", original.getValue("1"));
assertEquals("222", original.getValue("2"));
assertEquals("333", original.getValue("3"));
}
@Test
public void testPutAll_sizePowerOfTwo() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "aaa");
original.putValue("b", "bbb");
original.putValue("c", "ccc");
original.putValue("d", "ddd");
assertEquals(4, original.size(), "size");
// add empty context data
original.putAll(new SortedArrayStringMap());
assertEquals(4, original.size(), "size after put empty");
assertEquals("aaa", original.getValue("a"));
assertEquals("bbb", original.getValue("b"));
assertEquals("ccc", original.getValue("c"));
assertEquals("ddd", original.getValue("d"));
final SortedArrayStringMap other = new SortedArrayStringMap();
other.putValue("1", "111");
other.putValue("2", "222");
other.putValue("3", "333");
other.putValue("4", "444");
original.putAll(other);
assertEquals(8, original.size(), "size after put other");
assertEquals("aaa", original.getValue("a"));
assertEquals("bbb", original.getValue("b"));
assertEquals("ccc", original.getValue("c"));
assertEquals("ddd", original.getValue("d"));
assertEquals("111", original.getValue("1"));
assertEquals("222", original.getValue("2"));
assertEquals("333", original.getValue("3"));
assertEquals("444", original.getValue("4"));
}
@Test
public void testPutAll_largeAddition() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue(null, "nullVal");
original.putValue("a", "aaa");
original.putValue("b", "bbb");
original.putValue("c", "ccc");
original.putValue("d", "ddd");
assertEquals(5, original.size(), "size");
final SortedArrayStringMap other = new SortedArrayStringMap();
for (int i = 0 ; i < 500; i++) {
other.putValue(String.valueOf(i), String.valueOf(i));
}
other.putValue(null, "otherVal");
original.putAll(other);
assertEquals(505, original.size(), "size after put other");
assertEquals("otherVal", original.getValue(null));
assertEquals("aaa", original.getValue("a"));
assertEquals("bbb", original.getValue("b"));
assertEquals("ccc", original.getValue("c"));
assertEquals("ddd", original.getValue("d"));
for (int i = 0 ; i < 500; i++) {
assertEquals(String.valueOf(i), original.getValue(String.valueOf(i)));
}
}
@Test
public void testPutAllSelfDoesNotModify() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "aaa");
original.putValue("b", "bbb");
original.putValue("c", "ccc");
assertEquals(3, original.size(), "size");
// putAll with self
original.putAll(original);
assertEquals(3, original.size(), "size after put empty");
assertEquals("aaa", original.getValue("a"));
assertEquals("bbb", original.getValue("b"));
assertEquals("ccc", original.getValue("c"));
}
@Test
public void testConcurrentModificationBiConsumerPut() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "aaa");
assertThrows(ConcurrentModificationException.class, () -> original.forEach((s, o) -> original.putValue("c", "other")));
}
@Test
public void testConcurrentModificationBiConsumerPutValue() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "aaa");
assertThrows(ConcurrentModificationException.class, () -> original.forEach((s, o) -> original.putValue("c", "other")));
}
@Test
public void testConcurrentModificationBiConsumerRemove() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "aaa");
assertThrows(ConcurrentModificationException.class, () -> original.forEach((s, o) -> original.remove("a")));
}
@Test
public void testConcurrentModificationBiConsumerClear() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "aaa");
assertThrows(ConcurrentModificationException.class, () -> original.forEach((s, o) -> original.clear()));
}
@Test
public void testConcurrentModificationTriConsumerPut() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "aaa");
assertThrows(ConcurrentModificationException.class, () -> original.forEach((s, o, o2) -> original.putValue("c", "other"), null));
}
@Test
public void testConcurrentModificationTriConsumerPutValue() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "aaa");
assertThrows(ConcurrentModificationException.class, () -> original.forEach((s, o, o2) -> original.putValue("c", "other"), null));
}
@Test
public void testConcurrentModificationTriConsumerRemove() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "aaa");
assertThrows(ConcurrentModificationException.class, () -> original.forEach((s, o, o2) -> original.remove("a"), null));
}
@Test
public void testConcurrentModificationTriConsumerClear() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "aaa");
assertThrows(ConcurrentModificationException.class, () -> original.forEach((s, o, o2) -> original.clear(), null));
}
@Test
public void testInitiallyNotFrozen() {
assertFalse(new SortedArrayStringMap().isFrozen());
}
@Test
public void testIsFrozenAfterCallingFreeze() {
final SortedArrayStringMap original = new SortedArrayStringMap();
assertFalse(original.isFrozen(), "before freeze");
original.freeze();
assertTrue(original.isFrozen(), "after freeze");
}
@Test
public void testFreezeProhibitsPutValue() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.freeze();
assertThrows(UnsupportedOperationException.class, () -> original.putValue("a", "aaa"));
}
@Test
public void testFreezeProhibitsRemove() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("b", "bbb");
original.freeze();
assertThrows(UnsupportedOperationException.class, () -> original.remove("b")); // existing key: modifies the collection
}
@Test
public void testFreezeAllowsRemoveOfNonExistingKey() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("b", "bbb");
original.freeze();
assertDoesNotThrow(() -> original.remove("a"));
}
@Test
public void testFreezeAllowsRemoveIfEmpty() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.freeze();
assertDoesNotThrow(() -> original.remove("a"));
}
@Test
public void testFreezeProhibitsClear() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "aaa");
original.freeze();
assertThrows(UnsupportedOperationException.class, original::clear);
}
@Test
public void testFreezeAllowsClearIfEmpty() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.freeze();
assertDoesNotThrow(original::clear);
}
@Test
public void testPutInsertsInAlphabeticOrder() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("B", "Bvalue");
original.putValue("3", "3value");
original.putValue("c", "cvalue");
original.putValue("d", "dvalue");
assertEquals("avalue", original.getValue("a"));
assertEquals("avalue", original.getValueAt(2));
assertEquals("Bvalue", original.getValue("B"));
assertEquals("Bvalue", original.getValueAt(1));
assertEquals("3value", original.getValue("3"));
assertEquals("3value", original.getValueAt(0));
assertEquals("cvalue", original.getValue("c"));
assertEquals("cvalue", original.getValueAt(3));
assertEquals("dvalue", original.getValue("d"));
assertEquals("dvalue", original.getValueAt(4));
}
@Test
public void testPutValueInsertsInAlphabeticOrder() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("B", "Bvalue");
original.putValue("3", "3value");
original.putValue("c", "cvalue");
original.putValue("d", "dvalue");
assertEquals("avalue", original.getValue("a"));
assertEquals("avalue", original.getValueAt(2));
assertEquals("Bvalue", original.getValue("B"));
assertEquals("Bvalue", original.getValueAt(1));
assertEquals("3value", original.getValue("3"));
assertEquals("3value", original.getValueAt(0));
assertEquals("cvalue", original.getValue("c"));
assertEquals("cvalue", original.getValueAt(3));
assertEquals("dvalue", original.getValue("d"));
assertEquals("dvalue", original.getValueAt(4));
}
@Test
public void testNullKeysAllowed() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("B", "Bvalue");
original.putValue("3", "3value");
original.putValue("c", "cvalue");
original.putValue("d", "dvalue");
assertEquals(5, original.size());
assertEquals("{3=3value, B=Bvalue, a=avalue, c=cvalue, d=dvalue}", original.toString());
original.putValue(null, "nullvalue");
assertEquals(6, original.size());
assertEquals("{null=nullvalue, 3=3value, B=Bvalue, a=avalue, c=cvalue, d=dvalue}", original.toString());
original.putValue(null, "otherNullvalue");
assertEquals("{null=otherNullvalue, 3=3value, B=Bvalue, a=avalue, c=cvalue, d=dvalue}", original.toString());
assertEquals(6, original.size());
original.putValue(null, "nullvalue");
assertEquals(6, original.size());
assertEquals("{null=nullvalue, 3=3value, B=Bvalue, a=avalue, c=cvalue, d=dvalue}", original.toString());
original.putValue(null, "abc");
assertEquals(6, original.size());
assertEquals("{null=abc, 3=3value, B=Bvalue, a=avalue, c=cvalue, d=dvalue}", original.toString());
}
@Test
public void testNullKeysCopiedToAsMap() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("B", "Bvalue");
original.putValue("3", "3value");
original.putValue("c", "cvalue");
original.putValue("d", "dvalue");
assertEquals(5, original.size());
final HashMap<String, String> expected = new HashMap<>();
expected.put("a", "avalue");
expected.put("B", "Bvalue");
expected.put("3", "3value");
expected.put("c", "cvalue");
expected.put("d", "dvalue");
assertEquals(expected, original.toMap(), "initial");
original.putValue(null, "nullvalue");
expected.put(null, "nullvalue");
assertEquals(6, original.size());
assertEquals(expected, original.toMap(), "with null key");
original.putValue(null, "otherNullvalue");
expected.put(null, "otherNullvalue");
assertEquals(6, original.size());
assertEquals(expected, original.toMap(), "with null key value2");
original.putValue(null, "nullvalue");
expected.put(null, "nullvalue");
assertEquals(6, original.size());
assertEquals(expected, original.toMap(), "with null key value1 again");
original.putValue(null, "abc");
expected.put(null, "abc");
assertEquals(6, original.size());
assertEquals(expected, original.toMap(), "with null key value3");
}
@Test
public void testRemove() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
assertEquals(1, original.size());
assertEquals("avalue", original.getValue("a"));
original.remove("a");
assertEquals(0, original.size());
assertNull(original.getValue("a"), "no a val");
original.remove("B");
assertEquals(0, original.size());
assertNull(original.getValue("B"), "no B val");
}
@Test
public void testRemoveNullsOutRemovedSlot() throws Exception {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("b", "bvalue");
original.putValue("c", "cvalue");
original.putValue("d", "dvalue");
original.remove("a");
original.remove("b");
original.remove("c");
original.remove("d");
assertNull(original.getValueAt(0));
// ensure slots in the values array are nulled out
final Field f = SortedArrayStringMap.class.getDeclaredField("values");
f.setAccessible(true);
final Object[] values = (Object[]) f.get(original);
assertAll(Arrays.stream(values).map(value -> () -> assertNull(value)));
}
@Test
public void testRemoveWhenFull() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("b", "bvalue");
original.putValue("c", "cvalue");
original.putValue("d", "dvalue"); // default capacity = 4
original.remove("d");
}
@Test
public void testNullValuesArePreserved() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
assertEquals(1, original.size());
assertEquals("avalue", original.getValue("a"));
original.putValue("a", null);
assertEquals(1, original.size());
assertNull(original.getValue("a"), "no a val");
original.putValue("B", null);
assertEquals(2, original.size());
assertNull(original.getValue("B"), "no B val");
}
@Test
public void testGet() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("B", "Bvalue");
original.putValue("3", "3value");
assertEquals("avalue", original.getValue("a"));
assertEquals("Bvalue", original.getValue("B"));
assertEquals("3value", original.getValue("3"));
original.putValue("0", "0value");
assertEquals("0value", original.getValue("0"));
assertEquals("3value", original.getValue("3"));
assertEquals("Bvalue", original.getValue("B"));
assertEquals("avalue", original.getValue("a"));
}
@Test
public void testGetValue_GetValueAt() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("B", "Bvalue");
original.putValue("3", "3value");
assertEquals("avalue", original.getValue("a"));
assertEquals("avalue", original.getValueAt(2));
assertEquals("Bvalue", original.getValue("B"));
assertEquals("Bvalue", original.getValueAt(1));
assertEquals("3value", original.getValue("3"));
assertEquals("3value", original.getValueAt(0));
original.putValue("0", "0value");
assertEquals("0value", original.getValue("0"));
assertEquals("0value", original.getValueAt(0));
assertEquals("3value", original.getValue("3"));
assertEquals("3value", original.getValueAt(1));
assertEquals("Bvalue", original.getValue("B"));
assertEquals("Bvalue", original.getValueAt(2));
assertEquals("avalue", original.getValue("a"));
assertEquals("avalue", original.getValueAt(3));
}
@Test
public void testClear() throws Exception {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("B", "Bvalue");
original.putValue("3", "3value");
assertEquals(3, original.size());
original.clear();
assertEquals(0, original.size());
// ensure slots in the values array are nulled out
final Field f = SortedArrayStringMap.class.getDeclaredField("values");
f.setAccessible(true);
final Object[] values = (Object[]) f.get(original);
assertAll(Arrays.stream(values).map(value -> () -> assertNull(value)));
}
@Test
public void testIndexOfKey() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
assertEquals(0, original.indexOfKey("a"));
original.putValue("B", "Bvalue");
assertEquals(1, original.indexOfKey("a"));
assertEquals(0, original.indexOfKey("B"));
original.putValue("3", "3value");
assertEquals(2, original.indexOfKey("a"));
assertEquals(1, original.indexOfKey("B"));
assertEquals(0, original.indexOfKey("3"));
original.putValue("A", "AAA");
assertEquals(3, original.indexOfKey("a"));
assertEquals(2, original.indexOfKey("B"));
assertEquals(1, original.indexOfKey("A"));
assertEquals(0, original.indexOfKey("3"));
original.putValue("C", "CCC");
assertEquals(4, original.indexOfKey("a"));
assertEquals(3, original.indexOfKey("C"));
assertEquals(2, original.indexOfKey("B"));
assertEquals(1, original.indexOfKey("A"));
assertEquals(0, original.indexOfKey("3"));
original.putValue("2", "222");
assertEquals(5, original.indexOfKey("a"));
assertEquals(4, original.indexOfKey("C"));
assertEquals(3, original.indexOfKey("B"));
assertEquals(2, original.indexOfKey("A"));
assertEquals(1, original.indexOfKey("3"));
assertEquals(0, original.indexOfKey("2"));
}
@Test
public void testContainsKey() {
final SortedArrayStringMap original = new SortedArrayStringMap();
assertFalse(original.containsKey("a"), "a");
assertFalse(original.containsKey("B"), "B");
assertFalse(original.containsKey("3"), "3");
assertFalse(original.containsKey("A"), "A");
original.putValue("a", "avalue");
assertTrue(original.containsKey("a"), "a");
assertFalse(original.containsKey("B"), "B");
assertFalse(original.containsKey("3"), "3");
assertFalse(original.containsKey("A"), "A");
original.putValue("B", "Bvalue");
assertTrue(original.containsKey("a"), "a");
assertTrue(original.containsKey("B"), "B");
assertFalse(original.containsKey("3"), "3");
assertFalse(original.containsKey("A"), "A");
original.putValue("3", "3value");
assertTrue(original.containsKey("a"), "a");
assertTrue(original.containsKey("B"), "B");
assertTrue(original.containsKey("3"), "3");
assertFalse(original.containsKey("A"), "A");
original.putValue("A", "AAA");
assertTrue(original.containsKey("a"), "a");
assertTrue(original.containsKey("B"), "B");
assertTrue(original.containsKey("3"), "3");
assertTrue(original.containsKey("A"), "A");
}
@Test
public void testGetValueAt() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
assertEquals("a", original.getKeyAt(0));
assertEquals("avalue", original.getValueAt(0));
original.putValue("B", "Bvalue");
assertEquals("B", original.getKeyAt(0));
assertEquals("Bvalue", original.getValueAt(0));
assertEquals("a", original.getKeyAt(1));
assertEquals("avalue", original.getValueAt(1));
original.putValue("3", "3value");
assertEquals("3", original.getKeyAt(0));
assertEquals("3value", original.getValueAt(0));
assertEquals("B", original.getKeyAt(1));
assertEquals("Bvalue", original.getValueAt(1));
assertEquals("a", original.getKeyAt(2));
assertEquals("avalue", original.getValueAt(2));
}
@Test
public void testSizeAndIsEmpty() {
final SortedArrayStringMap original = new SortedArrayStringMap();
assertEquals(0, original.size());
assertTrue(original.isEmpty(), "initial");
original.putValue("a", "avalue");
assertEquals(1, original.size());
assertFalse(original.isEmpty(), "size=" + original.size());
original.putValue("B", "Bvalue");
assertEquals(2, original.size());
assertFalse(original.isEmpty(), "size=" + original.size());
original.putValue("3", "3value");
assertEquals(3, original.size());
assertFalse(original.isEmpty(), "size=" + original.size());
original.remove("B");
assertEquals(2, original.size());
assertFalse(original.isEmpty(), "size=" + original.size());
original.remove("3");
assertEquals(1, original.size());
assertFalse(original.isEmpty(), "size=" + original.size());
original.remove("a");
assertEquals(0, original.size());
assertTrue(original.isEmpty(), "size=" + original.size());
}
@Test
public void testForEachBiConsumer() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("B", "Bvalue");
original.putValue("3", "3value");
original.forEach(new BiConsumer<String, String>() {
int count = 0;
@Override
public void accept(final String key, final String value) {
assertEquals(key, original.getKeyAt(count), "key");
assertEquals(value, original.getValueAt(count), "val");
count++;
assertTrue(count <= original.size(), "count should not exceed size but was " + count);
}
});
}
static class State {
SortedArrayStringMap data;
int count;
}
static TriConsumer<String, String, State> COUNTER = (key, value, state) -> {
assertEquals(key, state.data.getKeyAt(state.count), "key");
assertEquals(value, state.data.getValueAt(state.count), "val");
state.count++;
assertTrue(
state.count <= state.data.size(), "count should not exceed size but was " + state.count);
};
@Test
public void testForEachTriConsumer() {
final SortedArrayStringMap original = new SortedArrayStringMap();
original.putValue("a", "avalue");
original.putValue("B", "Bvalue");
original.putValue("3", "3value");
final State state = new State();
state.data = original;
original.forEach(COUNTER, state);
assertEquals(state.count, original.size());
}
}