/*******************************************************************************
* Copyright 2014 Analog Devices, Inc.
*
* 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 com.analog.lyric.options.tests;
import static com.analog.lyric.util.test.ExceptionTester.*;
import static org.junit.Assert.*;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jdt.annotation.Nullable;
import org.junit.Test;
import com.analog.lyric.collect.ReleasableIterator;
import com.analog.lyric.options.AbstractOptionHolder;
import com.analog.lyric.options.IOption;
import com.analog.lyric.options.IOptionHolder;
import com.analog.lyric.options.IOptionKey;
import com.analog.lyric.options.IntegerOptionKey;
import com.analog.lyric.options.LocalOptionHolder;
import com.analog.lyric.options.Option;
import com.analog.lyric.options.StatelessOptionHolder;
import com.analog.lyric.options.StringOptionKey;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
/**
*
* @since 0.06
* @author CBarber
*/
public class TestOptionHolder
{
public final static IntegerOptionKey NOT_SET = new IntegerOptionKey(TestOptionHolder.class, "NOT_SET", 666);
public final static StringOptionKey K = new StringOptionKey(TestOptionHolder.class, "K");
public final static IntegerOptionKey I = new IntegerOptionKey(TestOptionHolder.class, "I");
public final static StringOptionKey L =
new StringOptionKey(TestOptionHolder.class, "L", "default", IOptionKey.Lookup.LOCAL);
@Test
public void test()
{
IOptionHolder holder = new StatelessOptionHolder(){};
assertInvariants(holder);
assertFalse(holder.supportsLocalOptions());
assertNull(holder.getOptionParent());
holder.clearLocalOptions(); // doesn't do anything
holder.unsetOption(K); // also doesn't do anything
assertNull(holder.getLocalOption(K));
assertNull(holder.getLocalOption(L));
expectThrow(UnsupportedOperationException.class, holder, "setOption", K, "foo");
assertEquals(0, Iterables.size(holder.getLocalOptions()));
holder = new LocalOptionHolder();
assertInvariants(holder);
assertTrue(holder.supportsLocalOptions());
assertNull(holder.getOptionParent());
holder.unsetOption(K);
assertNull(holder.getLocalOption(K));
assertNull(holder.getOption(K));
assertEquals(1, Iterators.size(holder.getOptionDelegates()));
assertEquals(0, Iterables.size(holder.getLocalOptions()));
holder.setOption(K, "hi");
assertEquals("hi", holder.getLocalOption(K));
assertEquals("hi", holder.getOption(K));
assertInvariants(holder);
holder.setOption(K, "bye");
assertEquals("bye", holder.getOption(K));
holder.unsetOption(K);
assertEquals("", holder.getOptionOrDefault(K));
assertNull(holder.getOption(K));
holder.setOption(K, "k");
holder.setOption(I, 42);
assertEquals("k", holder.getOption(K));
assertEquals((Integer)42, holder.getOption(I));
assertInvariants(holder);
assertEquals(2, Iterables.size(holder.getLocalOptions()));
holder.clearLocalOptions();
assertNull(holder.getOption(K));
assertNull(holder.getOption(I));
assertEquals(0, Iterables.size(holder.getLocalOptions()));
final IOptionHolder parent = holder;
AbstractOptionHolder child = new LocalOptionHolder() {
@Override
public @Nullable IOptionHolder getOptionParent()
{
return parent;
}
};
IOptionHolder[] source = new IOptionHolder[2];
assertInvariants(child);
assertNull(child.getOption(K));
parent.setOption(K, "bar");
parent.setOption(L, "bar");
assertEquals("bar", child.getOption(K));
assertEquals("bar", child.getOptionAndSource(K, null));
assertEquals("bar", child.getOptionAndSource(K, new IOptionHolder[0]));
assertEquals("bar", child.getOptionAndSource(K, source));
assertEquals(null, child.getOption(L));
assertEquals("default", child.getOptionOrDefault(L));
assertEquals("bar", parent.getOption(L));
assertArrayEquals(new Object[] { parent, null }, source);
assertInvariants(child);
child.setOption(K, "gag");
child.setOption(L, "gag");
assertEquals("gag", child.getOption(K));
assertEquals("gag", child.getOptionAndSource(K, source));
assertEquals("gag", child.getOption(L));
assertArrayEquals(new Object[] { child, null }, source);
assertInvariants(child);
assertNull(child.getOptionAndSource(NOT_SET, source));
assertArrayEquals(new Object[] { child, null }, source); // not modified
source[0] = null;
assertNull(child.getOptionAndSource(NOT_SET, source));
assertArrayEquals(new Object[] { null, null }, source);
}
/**
* Unit test for {@link Option} class.
*
* @since 0.07
*/
@Test
public void testOption()
{
Option<String> strOption = new Option<String>(K);
assertSame(K, strOption.key());
assertEquals("", strOption.value());
assertEquals(strOption, strOption);
assertEquals(strOption, new Option<String>(K, ""));
assertEquals(strOption.hashCode(), new Option<String>(K).hashCode());
assertNotEquals(strOption, "");
assertNotEquals(strOption, new Option<String>(K, "x"));
assertNotEquals(strOption, new Option<Integer>(I));
strOption = new Option<String>(K, "foo");
assertEquals("foo", strOption.value());
assertEquals("TestOptionHolder.K=foo", strOption.toString());
strOption = new Option<String>(K, null);
assertNull(strOption.value());
IOptionHolder holder = new LocalOptionHolder();
Option.setOptions(holder, Option.create(K, "a"), Option.create(I, 42));
assertEquals(Option.create(K, "a"), Option.lookup(holder, K));
assertEquals(Option.create(I, 42), Option.lookup(holder, I));
Option.setOptions(holder, Option.create(I, null));
assertNull(holder.getOption(I));
}
private void assertInvariants(IOptionHolder holder)
{
Set<IOptionKey<?>> seen = new HashSet<IOptionKey<?>>();
for (IOption<?> option : holder.getLocalOptions())
{
assertTrue(seen.add(option.key()));
assertEquals(option.value(), holder.getLocalOption(option.key()));
assertEquals(option.value(), holder.getOption(option.key()));
assertEquals(option.value(), holder.getOptionOrDefault(option.key()));
}
assertNull(holder.getLocalOption(NOT_SET));
assertNull(holder.getOption(NOT_SET));
assertEquals(NOT_SET.defaultValue(), holder.getOptionOrDefault(NOT_SET));
ReleasableIterator<? extends IOptionHolder> delegates = holder.getOptionDelegates();
assertTrue(delegates.hasNext());
assertSame(holder, delegates.next());
while (delegates.hasNext())
{
IOptionHolder delegate = delegates.next();
assertNotSame(delegate, holder);
for (IOption<?> option : delegate.getLocalOptions())
{
final IOptionKey<?> key = option.key();
if (seen.add(key))
{
assertEquals(option.value(), delegate.getLocalOption(key));
if (option.key().local())
{
assertNull(holder.getOption(key));
}
else
{
assertEquals(option.value(), holder.getOption(key));
}
}
else
{
// Option is set, but value will come from previous delegate.
assertNotNull(holder.getOption(key));
}
}
}
delegates.release();
}
}