package org.trimou.engine.resolver;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.math.BigDecimal;
import java.util.Map;
import org.junit.Test;
import org.trimou.AbstractEngineTest;
import org.trimou.ArchiveType;
import org.trimou.Hammer;
import org.trimou.Mustache;
import org.trimou.engine.MustacheEngineBuilder;
import org.trimou.util.ImmutableMap;
/**
*
* @author Martin Kouba
*/
public class ReflectionResolverTest extends AbstractEngineTest {
@Test
public void testResolution() {
ReflectionResolver resolver = new ReflectionResolver();
// Just to init the resolver
MustacheEngineBuilder.newBuilder()
.omitServiceLoaderConfigurationExtensions()
.addResolver(resolver).build();
Hammer hammer = new Hammer();
assertNull(resolver.resolve(null, "whatever", null));
assertNotNull(resolver.resolve(hammer, "age", null));
// Methods have higher priority
assertEquals(10, resolver.resolve(hammer, "age", null));
assertNull(resolver.resolve(hammer, "getAgeForName", null));
}
@Test
public void testInterpolation() {
int[] array = new int[] { 1, 2 };
Map<String, Object> data = ImmutableMap.of("hammer",
new Hammer(), "type", ArchiveType.class, "array", array);
assertEquals("Hello Edgar of age 10, persistent: false and !",
engine.compileMustache("reflection_resolver",
"Hello {{hammer.name}} of age {{hammer.age}}, persistent: {{hammer.persistent}} and {{hammer.invalidName}}!")
.render(data));
assertEquals(
"NAIL|jar", engine
.compileMustache("reflection_resolver_fields",
"{{hammer.nail}}|{{type.JAR.suffix}}")
.render(data));
assertEquals("jar,war,ear,",
engine.compileMustache("reflection_resolver_static_method",
"{{#type.values}}{{this.suffix}},{{/type.values}}")
.render(data));
assertEquals("" + array.length,
engine.compileMustache("reflection_resolver_array",
"{{array.length}}").render(data));
}
@Test
public void testPublicMethodOnPackagePrivateClass() {
Hammer data = new Hammer();
Mustache mustache = engine.compileMustache(
"reflection_resolver_accessibility",
"{{#this.map.entrySet}}{{key}}={{value}}{{/this.map.entrySet}}");
assertEquals("foo=10", mustache.render(data));
assertEquals("foo=10", mustache.render(data));
}
@Test
public void testMemberCacheInvalidation() {
final ReflectionResolver resolver = new ReflectionResolver();
// Just to init the resolver
MustacheEngineBuilder.newBuilder()
.omitServiceLoaderConfigurationExtensions()
.addResolver(resolver).build();
Hammer hammer = new Hammer();
assertNotNull(resolver.resolve(hammer, "age", null));
resolver.invalidateMemberCache(null);
assertEquals(0, resolver.getMemberCacheSize());
assertNotNull(resolver.resolve(hammer, "age", null));
assertNotNull(resolver.resolve(ArchiveType.class, "JAR", null));
resolver.invalidateMemberCache((input) -> input.getName().equals(ArchiveType.class.getName()));
assertEquals(1, resolver.getMemberCacheSize());
}
@Test(expected = IllegalStateException.class)
public void testMultipleInit() {
ReflectionResolver resolver = new ReflectionResolver();
// Just to init the resolver
MustacheEngineBuilder.newBuilder()
.omitServiceLoaderConfigurationExtensions()
.addResolver(resolver).build();
resolver.init(null);
}
@Test
public void testGetMembers() {
assertNotNull(ReflectionResolver.findMethod(Charlie.class, "name"));
assertNotNull(ReflectionResolver.findMethod(Charlie.class, "old"));
assertNotNull(
ReflectionResolver.findMethod(Charlie.class, "hasSomething"));
assertNotNull(
ReflectionResolver.findMethod(Charlie.class, "getAnotherName"));
assertNotNull(
ReflectionResolver.findMethod(Charlie.class, "anotherName"));
assertNotNull(ReflectionResolver.findMethod(Charlie.class, "isOk"));
assertNotNull(ReflectionResolver.findMethod(Charlie.class, "ok"));
assertNotNull(ReflectionResolver.findMethod(Charlie.class, "info"));
assertNull(ReflectionResolver.findMethod(Charlie.class, "getPrice"));
assertNotNull(
ReflectionResolver.findField(Charlie.class, "publicField"));
assertNull(ReflectionResolver.findField(Charlie.class, "privateField"));
}
public static class Alpha {
@SuppressWarnings("unused")
private String privateField;
// OK
public String getName() {
return null;
}
// OK
public int isOld() {
return 1;
}
// OK
public boolean hasSomething() {
return true;
}
// Not read method - private
@SuppressWarnings("unused")
private BigDecimal getPrice() {
return null;
}
// OK
public String getInfo() {
return null;
}
// Not read method - protected
protected String getProtected() {
return null;
}
}
public static class Bravo extends Alpha {
public final String publicField = "foo";
// Not read method - has param
public String getWithParam(String param) {
return null;
}
// Not read method - no return value
public void getNoReturnValue() {
}
// OK
public String getAnotherName() {
return null;
}
}
public static class Charlie extends Bravo {
// OK
public Boolean isOk() {
return null;
}
}
}