package org.jooby.internal; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.expectLastCall; import static org.easymock.EasyMock.isA; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertSame; import java.io.InputStream; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.net.URL; import org.jooby.Env; import org.jooby.test.MockUnit; import org.junit.Test; import org.junit.runner.RunWith; import org.objectweb.asm.ClassReader; import org.objectweb.asm.ClassVisitor; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import com.google.common.io.Resources; import com.typesafe.config.Config; @RunWith(PowerMockRunner.class) @PrepareForTest({RouteMetadata.class, Resources.class, URL.class, ClassReader.class }) public class RouteMetadataTest { public static class Mvc { public Mvc() { } public Mvc(final String s) { } public void noarg() { } public void arg(final double v) { } public void arg(final String x) { } public void arg(final double v, final int u) { } public static void staticMethod() { } } @Test public void noargconst() throws Exception { new MockUnit(Config.class) .expect(unit -> { Config config = unit.get(Config.class); expect(config.hasPath("application.env")).andReturn(true); expect(config.getString("application.env")).andReturn("dev"); }) .run(unit -> { Constructor<?> constructor = Mvc.class.getDeclaredConstructor(); RouteMetadata ci = new RouteMetadata(Env.DEFAULT.build(unit.get(Config.class))); assertArrayEquals(new String[0], ci.names(constructor)); assertEquals(35, ci.startAt(constructor)); }); } @Test public void consArgS() throws Exception { new MockUnit(Config.class) .expect(unit -> { Config config = unit.get(Config.class); expect(config.hasPath("application.env")).andReturn(true); expect(config.getString("application.env")).andReturn("dev"); }) .run(unit -> { Constructor<?> constructor = Mvc.class.getDeclaredConstructor(String.class); RouteMetadata ci = new RouteMetadata(Env.DEFAULT.build(unit.get(Config.class))); assertArrayEquals(new String[]{"s" }, ci.names(constructor)); assertEquals(38, ci.startAt(constructor)); }); } @Test public void noargmethod() throws Exception { new MockUnit(Config.class) .expect(unit -> { Config config = unit.get(Config.class); expect(config.hasPath("application.env")).andReturn(true); expect(config.getString("application.env")).andReturn("dev"); }) .run(unit -> { Method m = Mvc.class.getDeclaredMethod("noarg"); RouteMetadata ci = new RouteMetadata(Env.DEFAULT.build(unit.get(Config.class))); assertArrayEquals(new String[0], ci.names(m)); assertEquals(43, ci.startAt(m)); }); } @Test public void argI() throws Exception { new MockUnit(Config.class) .expect(unit -> { Config config = unit.get(Config.class); expect(config.hasPath("application.env")).andReturn(true); expect(config.getString("application.env")).andReturn("dev"); }) .run(unit -> { Method m = Mvc.class.getDeclaredMethod("arg", double.class); RouteMetadata ci = new RouteMetadata(Env.DEFAULT.build(unit.get(Config.class))); assertArrayEquals(new String[]{"v" }, ci.names(m)); assertEquals(47, ci.startAt(m)); }); } @Test public void argS() throws Exception { new MockUnit(Config.class) .expect(unit -> { Config config = unit.get(Config.class); expect(config.hasPath("application.env")).andReturn(true); expect(config.getString("application.env")).andReturn("dev"); }) .run(unit -> { Method m = Mvc.class.getDeclaredMethod("arg", String.class); RouteMetadata ci = new RouteMetadata(Env.DEFAULT.build(unit.get(Config.class))); assertArrayEquals(new String[]{"x" }, ci.names(m)); assertEquals(51, ci.startAt(m)); }); } @Test public void argVU() throws Exception { new MockUnit(Config.class) .expect(unit -> { Config config = unit.get(Config.class); expect(config.hasPath("application.env")).andReturn(true); expect(config.getString("application.env")).andReturn("dev"); }) .run(unit -> { Method m = Mvc.class.getDeclaredMethod("arg", double.class, int.class); RouteMetadata ci = new RouteMetadata(Env.DEFAULT.build(unit.get(Config.class))); assertArrayEquals(new String[]{"v", "u" }, ci.names(m)); assertEquals(55, ci.startAt(m)); }); } @Test public void nocache() throws Exception { new MockUnit(Config.class) .expect(unit -> { Config config = unit.get(Config.class); expect(config.hasPath("application.env")).andReturn(true); expect(config.getString("application.env")).andReturn("dev"); }) .run(unit -> { Method m = Mvc.class.getDeclaredMethod("arg", String.class); RouteMetadata ci = new RouteMetadata(Env.DEFAULT.build(unit.get(Config.class))); String[] params1 = ci.names(m); String[] params2 = ci.names(m); assertNotSame(params1, params2); }); } @Test public void nocacheMavenBuild() throws Exception { InputStream stream = getClass().getResourceAsStream("RouteMetadataTest$Mvc.bc"); new MockUnit(Config.class) .expect(unit -> { Config config = unit.get(Config.class); expect(config.hasPath("application.env")).andReturn(true); expect(config.getString("application.env")).andReturn("dev"); }) .expect(unit -> { URL resource = unit.mock(URL.class); expect(resource.openStream()).andReturn(stream); unit.mockStatic(Resources.class); expect(Resources.getResource(Mvc.class, "RouteMetadataTest$Mvc.class")) .andReturn(resource); }) .run(unit -> { Method method = Mvc.class.getDeclaredMethod("arg", String.class); RouteMetadata ci = new RouteMetadata(Env.DEFAULT.build(unit.get(Config.class))); String[] params = ci.names(method); assertEquals("x", params[0]); }); } @Test(expected = IllegalStateException.class) public void cannotReadByteCode() throws Exception { new MockUnit(Config.class) .expect(unit -> { Config config = unit.get(Config.class); expect(config.hasPath("application.env")).andReturn(true); expect(config.getString("application.env")).andReturn("dev"); }) .expect(unit -> { InputStream stream = unit.mock(InputStream.class); stream.close(); URL resource = unit.mock(URL.class); expect(resource.openStream()).andReturn(stream); ClassReader reader = unit .mockConstructor(ClassReader.class, new Class[]{InputStream.class }, stream); reader.accept(isA(ClassVisitor.class), eq(0)); expectLastCall().andThrow(new NullPointerException("intentional err")); unit.mockStatic(Resources.class); expect(Resources.getResource(Mvc.class, "RouteMetadataTest$Mvc.class")) .andReturn(resource); }) .run(unit -> { Method method = Mvc.class.getDeclaredMethod("arg", String.class); RouteMetadata ci = new RouteMetadata(Env.DEFAULT.build(unit.get(Config.class))); String[] params = ci.names(method); assertEquals("x", params[0]); }); } @Test public void withcache() throws Exception { new MockUnit(Config.class) .expect(unit -> { Config config = unit.get(Config.class); expect(config.hasPath("application.env")).andReturn(true); expect(config.getString("application.env")).andReturn("prod"); }) .run(unit -> { Method m = Mvc.class.getDeclaredMethod("arg", String.class); RouteMetadata ci = new RouteMetadata(Env.DEFAULT.build(unit.get(Config.class))); String[] params1 = ci.names(m); String[] params2 = ci.names(m); assertSame(params1, params2); }); } }