/*
* Copyright 2016 LINE Corporation
*
* LINE Corporation 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.
*/
/*
* Copyright 2012 The Netty Project
*
* The Netty Project 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 com.linecorp.armeria.internal;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Before;
import org.junit.Test;
import com.google.common.collect.Lists;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
public class DefaultAttributeMapTest {
private DefaultAttributeMap map;
@Before
public void setup() {
map = new DefaultAttributeMap();
}
@Test
public void testMapExists() {
assertNotNull(map);
}
@Test
public void testGetSetString() {
AttributeKey<String> key = AttributeKey.valueOf("Nothing");
Attribute<String> one = map.attr(key);
assertSame(one, map.attr(key));
one.setIfAbsent("Whoohoo");
assertSame("Whoohoo", one.get());
one.setIfAbsent("What");
assertNotSame("What", one.get());
one.remove();
assertNull(one.get());
}
@Test
public void testGetSetInt() {
AttributeKey<Integer> key = AttributeKey.valueOf("Nada");
Attribute<Integer> one = map.attr(key);
assertSame(one, map.attr(key));
one.setIfAbsent(3653);
assertEquals(Integer.valueOf(3653), one.get());
one.setIfAbsent(1);
assertNotSame(1, one.get());
one.remove();
assertNull(one.get());
}
// See https://github.com/netty/netty/issues/2523
@Test
public void testSetRemove() {
AttributeKey<Integer> key = AttributeKey.valueOf("key");
Attribute<Integer> attr = map.attr(key);
attr.set(1);
assertSame(1, attr.getAndRemove());
Attribute<Integer> attr2 = map.attr(key);
attr2.set(2);
assertSame(2, attr2.get());
assertNotSame(attr, attr2);
}
@Test
public void testGetAndSetWithNull() {
AttributeKey<Integer> key = AttributeKey.valueOf("key");
Attribute<Integer> attr = map.attr(key);
attr.set(1);
assertSame(1, attr.getAndSet(null));
Attribute<Integer> attr2 = map.attr(key);
attr2.set(2);
assertSame(2, attr2.get());
assertSame(attr, attr2);
}
@Test
public void testIteratorWithEmptyMap() {
assertThat(map.attrs().hasNext(), is(false));
}
@Test
public void testIteratorWithSparseMap() {
final AttributeKey<Integer> key = AttributeKey.valueOf(DefaultAttributeMap.class, "KEY");
map.attr(key).set(42);
final List<Attribute<?>> attrs = Lists.newArrayList(map.attrs());
assertEquals(Collections.singletonList(map.attr(key)), attrs);
map.attr(key).remove();
assertFalse(map.attrs().hasNext());
}
@Test
public void testIteratorWithFullMap() {
final List<AttributeKey<Integer>> expectedKeys = new ArrayList<>();
for (int i = 0; i < 1024; i++) {
final AttributeKey<Integer> key =
AttributeKey.valueOf(DefaultAttributeMapTest.class, String.valueOf(i));
expectedKeys.add(key);
map.attr(key).set(i);
}
// Make sure all buckets are filled.
for (int i = 0; i < map.attributes.length(); i++) {
assertNotNull(map.attributes.get(i));
}
// Make sure the Iterator yields all attributes.
assertEquals(expectedKeys, actualKeys());
// Make sure the Iterator does not yield the attributes whose 'removed' property is 'true'.
for (int i = 0; i < map.attributes.length(); i++) {
Attribute<?> a = map.attributes.get(i);
a.remove();
// A head attribute is never removed from the linked list.
assertSame(a, map.attributes.get(i));
// Remove the removed key from the list of expected expectedKeys.
expectedKeys.remove(a.key());
}
assertEquals(expectedKeys, actualKeys());
}
private List<AttributeKey<?>> actualKeys() {
return Lists.newArrayList(map.attrs()).stream().sorted((a, b) -> {
Integer aVal = a.key().id();
Integer bVal = b.key().id();
return aVal.compareTo(bVal);
}).map(Attribute::key).collect(Collectors.toList());
}
}