package com.laytonsmith.testing; import com.laytonsmith.PureUtilities.ClassLoading.ClassDiscovery; import com.laytonsmith.PureUtilities.Common.ReflectionUtils; import com.laytonsmith.PureUtilities.Common.StreamUtils; import com.laytonsmith.PureUtilities.Common.StringUtils; import com.laytonsmith.abstraction.AbstractionObject; import com.laytonsmith.abstraction.MCLocation; import com.laytonsmith.abstraction.MCPlayer; import com.laytonsmith.abstraction.MCServer; import com.laytonsmith.abstraction.MCWorld; import com.laytonsmith.abstraction.bukkit.BukkitMCCommandSender; import com.laytonsmith.abstraction.bukkit.entities.BukkitMCPlayer; import com.laytonsmith.annotations.api; import com.laytonsmith.annotations.typeof; import com.laytonsmith.commandhelper.CommandHelperPlugin; import com.laytonsmith.core.MethodScriptComplete; import com.laytonsmith.core.ObjectGenerator; import com.laytonsmith.core.SimpleDocumentation; import com.laytonsmith.core.Static; import com.laytonsmith.core.constructs.CArray; import com.laytonsmith.core.constructs.CBoolean; import com.laytonsmith.core.constructs.CClassType; import com.laytonsmith.core.constructs.CDouble; import com.laytonsmith.core.constructs.CFunction; import com.laytonsmith.core.constructs.CInt; import com.laytonsmith.core.constructs.CNull; import com.laytonsmith.core.constructs.CString; import com.laytonsmith.core.constructs.CVoid; import com.laytonsmith.core.constructs.Command; import com.laytonsmith.core.constructs.Construct; import com.laytonsmith.core.constructs.IVariable; import com.laytonsmith.core.constructs.Target; import com.laytonsmith.core.constructs.Variable; import com.laytonsmith.core.environments.Environment; import com.laytonsmith.core.environments.GlobalEnv; import com.laytonsmith.core.exceptions.CRE.CREPluginInternalException; import com.laytonsmith.core.exceptions.ConfigRuntimeException; import com.laytonsmith.core.exceptions.MarshalException; import com.laytonsmith.core.functions.DummyFunction; import com.laytonsmith.core.functions.FunctionBase; import com.laytonsmith.core.functions.FunctionList; import com.laytonsmith.persistence.PersistenceNetwork; import com.laytonsmith.persistence.io.ConnectionMixinFactory; import org.bukkit.entity.Player; import org.junit.Before; import org.junit.Test; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URI; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.TreeSet; import java.util.logging.Level; import java.util.logging.Logger; import static com.laytonsmith.testing.StaticTest.Run; import static com.laytonsmith.testing.StaticTest.SRun; import java.util.HashSet; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.mockito.Mockito.*; import static com.laytonsmith.testing.StaticTest.Run; import static com.laytonsmith.testing.StaticTest.SRun; import static com.laytonsmith.testing.StaticTest.Run; import static com.laytonsmith.testing.StaticTest.SRun; import static com.laytonsmith.testing.StaticTest.Run; import static com.laytonsmith.testing.StaticTest.SRun; /** * * */ //@RunWith(PowerMockRunner.class) //@PrepareForTest(Static.class) public class RandomTests { MCPlayer fakePlayer; @Before public void setUp() throws Exception { fakePlayer = StaticTest.GetOnlinePlayer(); StaticTest.InstallFakeConvertor(fakePlayer); } private static final Set<String> testedFunctions = new TreeSet<>(); /** * This function automatically tests all the boilerplate portions of all * functions. Note that this can be disabled in the StaticTest class, so * that high quality test coverage can be measured. */ @Test @SuppressWarnings({"ThrowableResultIgnored", "CallToPrintStackTrace"}) public void testAllBoilerplate() { Map<String, Throwable> uhohs = new HashMap<>(); String[] requiredMethods = new String[]{"toString", "equals", "hashCode"}; //Ensure that all the abstraction objects overloaded StaticTest.InstallFakeServerFrontend(); outer: for (Class c : ClassDiscovery.getDefaultInstance().loadClassesThatExtend(AbstractionObject.class)) { inner: for (Class inter : c.getInterfaces()) { for (Class extended : inter.getInterfaces()) { if (extended == AbstractionObject.class && !c.isInterface()) { //This is a direct subclass of an interface that implements AbstractionObject, so check //to ensure that the equals, toString, and hashCode methods are overloaded. break inner; } } //It's not, so just skip it. continue outer; } Method[] methods = c.getDeclaredMethods(); required: for (String required : requiredMethods) { for (Method method : methods) { if (method.getName().equals(required)) { continue required; } } uhohs.put(c.getName() + " " + required, new NoSuchMethodException(c.getSimpleName() + " does not define " + required)); } } Set<String> classDocs = new TreeSet<>(); for (FunctionBase f : FunctionList.getFunctionList(null)) { try { if (testedFunctions.contains(f.getName())) { continue; } testedFunctions.add(f.getName()); StaticTest.TestBoilerplate(f, f.getName()); Class upper = f.getClass().getEnclosingClass(); if (upper == null) { fail(f.getName() + " is not enclosed in an upper class."); return; } try { Method m = upper.getMethod("docs", new Class[]{}); try { String docs = m.invoke(null, new Object[]{}).toString(); if (!classDocs.contains(docs)) { StaticTest.TestClassDocs(docs, upper); classDocs.add(docs); } } catch (NullPointerException ex) { fail(upper.getName() + "'s docs function should be static"); } } catch (IllegalAccessException | IllegalArgumentException | SecurityException ex) { Logger.getLogger(RandomTests.class.getName()).log(Level.SEVERE, null, ex); } catch (InvocationTargetException ex) { fail(upper.getName() + " throws an exception!"); } catch (NoSuchMethodException ex) { fail(upper.getName() + " does not include a class level documentation function."); } } catch (Throwable t) { uhohs.put(f.getClass().getName(), t); t.printStackTrace(); } } if (!StaticTest.brokenJunk.isEmpty()) { System.err.println("There " + StringUtils.PluralTemplateHelper(StaticTest.brokenJunk.size(), "is %d test that has", "are %d tests that have") + " a failure in extreme circumstances."); for(String s : StaticTest.brokenJunk){ uhohs.put(s, null); } } if (!uhohs.isEmpty()) { StringBuilder b = new StringBuilder(); for (String key : uhohs.keySet()) { b.append(key).append(" threw: ").append(uhohs.get(key)).append("\n"); } String output = ("There was/were " + uhohs.size() + " boilerplate failure(s). Output:\n" + b.toString()); StreamUtils.GetSystemOut().println(output); fail(output); } } @Test public void testConstuctToString() { assertEquals("hello", new CString("hello", Target.UNKNOWN).toString()); } @Test public void testClone() throws CloneNotSupportedException { CArray c1 = C.Array(C.Void(), C.Void()).clone(); CBoolean c2 = C.Boolean(true).clone(); CDouble c4 = C.Double(1).clone(); CFunction c5 = new CFunction("", Target.UNKNOWN).clone(); CInt c6 = C.Int(1).clone(); CNull c7 = C.Null().clone(); CString c8 = C.String("").clone(); CVoid c9 = C.Void().clone(); Command c10 = new Command("/c", Target.UNKNOWN).clone(); IVariable c12 = new IVariable(CClassType.AUTO, "@name", C.Null(), Target.UNKNOWN).clone(); Variable c13 = new Variable("$name", "", false, false, Target.UNKNOWN); } @Test public void testJSONEscapeString() throws MarshalException { CArray ca = new CArray(Target.UNKNOWN); final Target t = Target.UNKNOWN; ca.push(C.Int(1), t); ca.push(C.Double(2.2), t); ca.push(C.String("string"), t); ca.push(C.String("\"Quote\""), t); ca.push(C.Boolean(true), t); ca.push(C.Boolean(false), t); ca.push(C.Null(), t); ca.push(C.Void(), t); ca.push(new Command("/Command", Target.UNKNOWN), t); ca.push(new CArray(Target.UNKNOWN, new CInt(1, Target.UNKNOWN)), t); //[1, 2.2, "string", "\"Quote\"", true, false, null, "", "/Command", [1]] assertEquals("[1,2.2,\"string\",\"\\\"Quote\\\"\",true,false,null,\"\",\"\\/Command\",[1]]", Construct.json_encode(ca, Target.UNKNOWN)); } @Test public void testJSONDecodeString() throws MarshalException { CArray ca = new CArray(Target.UNKNOWN); ca.push(C.Int(1), Target.UNKNOWN); ca.push(C.Double(2.2), Target.UNKNOWN); ca.push(C.String("string"), Target.UNKNOWN); ca.push(C.String("\"Quote\""), Target.UNKNOWN); ca.push(C.Boolean(true), Target.UNKNOWN); ca.push(C.Boolean(false), Target.UNKNOWN); ca.push(C.Null(), Target.UNKNOWN); ca.push(C.Void(), Target.UNKNOWN); ca.push(new Command("/Command", Target.UNKNOWN), Target.UNKNOWN); ca.push(new CArray(Target.UNKNOWN, new CInt(1, Target.UNKNOWN)), Target.UNKNOWN); StaticTest.assertCEquals(ca, Construct.json_decode("[1, 2.2, \"string\", \"\\\"Quote\\\"\", true, false, null, \"\", \"\\/Command\", [1]]", Target.UNKNOWN)); } @Test public void testReturnArrayFromProc() throws Exception { assertEquals("{1, 2, 3}", SRun("proc(_test, @var, assign(@array, array(1, 2)) array_push(@array, @var) return(@array)) _test(3)", null)); } /*@Test*/ public void testStaticGetLocation() { MCWorld fakeWorld = mock(MCWorld.class); MCServer fakeServer = mock(MCServer.class); when(fakeServer.getWorld("world")).thenReturn(fakeWorld); CommandHelperPlugin.myServer = fakeServer; CArray ca1 = new CArray(Target.UNKNOWN, C.onstruct(1), C.onstruct(2), C.onstruct(3)); CArray ca2 = new CArray(Target.UNKNOWN, C.onstruct(1), C.onstruct(2), C.onstruct(3), C.onstruct("world")); CArray ca3 = new CArray(Target.UNKNOWN, C.onstruct(1), C.onstruct(2), C.onstruct(3), C.onstruct(45), C.onstruct(50)); CArray ca4 = new CArray(Target.UNKNOWN, C.onstruct(1), C.onstruct(2), C.onstruct(3), C.onstruct("world"), C.onstruct(45), C.onstruct(50)); MCLocation l1 = ObjectGenerator.GetGenerator().location(ca1, fakeWorld, Target.UNKNOWN); MCLocation l2 = ObjectGenerator.GetGenerator().location(ca2, fakeWorld, Target.UNKNOWN); MCLocation l3 = ObjectGenerator.GetGenerator().location(ca3, fakeWorld, Target.UNKNOWN); MCLocation l4 = ObjectGenerator.GetGenerator().location(ca4, fakeWorld, Target.UNKNOWN); assertEquals(fakeWorld, l1.getWorld()); assertEquals(fakeWorld, l2.getWorld()); assertEquals(fakeWorld, l3.getWorld()); assertEquals(fakeWorld, l4.getWorld()); assertEquals(1, l1.getX(), 0.00000000000000001); assertEquals(1, l2.getX(), 0.00000000000000001); assertEquals(1, l4.getX(), 0.00000000000000001); assertEquals(1, l4.getX(), 0.00000000000000001); assertEquals(2, l1.getY(), 0.00000000000000001); assertEquals(2, l2.getY(), 0.00000000000000001); assertEquals(2, l3.getY(), 0.00000000000000001); assertEquals(2, l4.getY(), 0.00000000000000001); assertEquals(3, l1.getZ(), 0.00000000000000001); assertEquals(3, l2.getZ(), 0.00000000000000001); assertEquals(3, l3.getZ(), 0.00000000000000001); assertEquals(3, l4.getZ(), 0.00000000000000001); assertEquals(0, l1.getYaw(), 0.0000000000000000001); assertEquals(0, l2.getYaw(), 0.0000000000000000001); assertEquals(45, l3.getYaw(), 0.0000000000000000001); assertEquals(45, l4.getYaw(), 0.0000000000000000001); assertEquals(0, l1.getPitch(), 0.0000000000000000001); assertEquals(0, l2.getPitch(), 0.0000000000000000001); assertEquals(50, l3.getPitch(), 0.0000000000000000001); assertEquals(50, l4.getPitch(), 0.0000000000000000001); CommandHelperPlugin.myServer = null; } @Test public void expressionTester() throws ConfigRuntimeException { //verify basic usage works String eClass = "com.sk89q.worldedit.internal.expression.Expression"; try { Class clazz = Class.forName(eClass); Object e = ReflectionUtils.invokeMethod(clazz, null, "compile", new Class[] { String.class, String.class, String.class }, new Object[] { "(x + 2) * y", "x", "y" }); double d = (double) ReflectionUtils.invokeMethod(clazz, e, "evaluate", new Class[] { double.class, double.class }, new Object[] { 2, 4 }); assertEquals(16, d, 0.00001); } catch (ClassNotFoundException cnf) { /* Not much we can really do about this during testing. throw new CREPluginInternalException("You are missing a required dependency: " + eClass, Target.UNKNOWN);*/ } catch (ReflectionUtils.ReflectionException rex) { throw new CREPluginInternalException("Your expression was invalidly formatted", Target.UNKNOWN, rex.getCause()); } } @Test public void testProcScope() throws Exception { SRun("proc(_b, assign(@a, 2)) assign(@a, 1) _b() msg(@a)", fakePlayer); verify(fakePlayer).sendMessage("1"); } @Test public void testCastFromBukkitMCPlayerToBukkitMCCommandSender() throws Exception { Player p = mock(Player.class); BukkitMCCommandSender c = new BukkitMCCommandSender(new BukkitMCPlayer(p)); } @Test public void testReflectDocs() throws Throwable { String ret = SRun("reflect_docs('reflect_docs', 'return')", null); assertEquals("string", ret); } @Test public void testGetValues() throws Exception { try{ Environment env = Static.GenerateStandaloneEnvironment(); GlobalEnv g = env.getEnv(GlobalEnv.class); ConnectionMixinFactory.ConnectionMixinOptions options; options = new ConnectionMixinFactory.ConnectionMixinOptions(); options.setWorkingDirectory(new File(".")); PersistenceNetwork network = new PersistenceNetwork("**=json://persistence.json", new URI("default"), options); ReflectionUtils.set(GlobalEnv.class, g, "persistenceNetwork", network); Run("store_value('t.test1', 'test')\n" + "store_value('t.test2', 'test')\n" + "store_value('t.test3.third', 'test')\n" + "msg(get_values('t'))", fakePlayer, new MethodScriptComplete() { @Override public void done(String output) { // } }, env); verify(fakePlayer).sendMessage("{t.test1: test, t.test2: test, t.test3.third: test}"); } finally { new File("persistence.json").deleteOnExit(); } } // @Test // public void testBlah() throws Throwable{ // StaticTest.InstallFakeConvertor(fakePlayer); // SRun("async_read('lsmith@localhost:/home/lsmith/test.txt', closure(@ret, @ex," // + "if(@ex != null, sys_out(@ex), sys_out(@ret))))", null); // } }