Cleanup Tests with JUnit5 and move to different modules

This commit is contained in:
Enrico Horn
2021-07-11 23:01:01 +02:00
parent 1a6de4a227
commit 9792fcb018
64 changed files with 2355 additions and 1806 deletions

View File

@@ -14,4 +14,12 @@
<name>luaj-core</name>
<description>Core code for LuaJ</description>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,115 @@
/*******************************************************************************
* Copyright (c) 2014 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.ByteArrayInputStream;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.Globals.BufferedStream;
class BufferedStreamTest {
private BufferedStream NewBufferedStream(int buflen, String contents) {
return new BufferedStream(buflen, new ByteArrayInputStream(contents.getBytes()));
}
@Test
void testReadEmptyStream() throws java.io.IOException {
BufferedStream bs = NewBufferedStream(4, "");
assertEquals(-1, bs.read());
assertEquals(-1, bs.read(new byte[10]));
assertEquals(-1, bs.read(new byte[10], 0, 10));
}
@Test
void testReadByte() throws java.io.IOException {
BufferedStream bs = NewBufferedStream(2, "abc");
assertEquals('a', bs.read());
assertEquals('b', bs.read());
assertEquals('c', bs.read());
assertEquals(-1, bs.read());
}
@Test
void testReadByteArray() throws java.io.IOException {
byte[] array = new byte[3];
BufferedStream bs = NewBufferedStream(4, "abcdef");
assertEquals(3, bs.read(array));
assertEquals("abc", new String(array));
assertEquals(1, bs.read(array));
assertEquals("d", new String(array, 0, 1));
assertEquals(2, bs.read(array));
assertEquals("ef", new String(array, 0, 2));
assertEquals(-1, bs.read());
}
@Test
void testReadByteArrayOffsetLength() throws java.io.IOException {
byte[] array = new byte[10];
BufferedStream bs = NewBufferedStream(8, "abcdefghijklmn");
assertEquals(4, bs.read(array, 0, 4));
assertEquals("abcd", new String(array, 0, 4));
assertEquals(4, bs.read(array, 2, 8));
assertEquals("efgh", new String(array, 2, 4));
assertEquals(6, bs.read(array, 0, 10));
assertEquals("ijklmn", new String(array, 0, 6));
assertEquals(-1, bs.read());
}
@Test
void testMarkOffsetBeginningOfStream() throws java.io.IOException {
byte[] array = new byte[4];
BufferedStream bs = NewBufferedStream(8, "abcdefghijkl");
assertEquals(true, bs.markSupported());
bs.mark(4);
assertEquals(4, bs.read(array));
assertEquals("abcd", new String(array));
bs.reset();
assertEquals(4, bs.read(array));
assertEquals("abcd", new String(array));
assertEquals(4, bs.read(array));
assertEquals("efgh", new String(array));
assertEquals(4, bs.read(array));
assertEquals("ijkl", new String(array));
assertEquals(-1, bs.read());
}
@Test
void testMarkOffsetMiddleOfStream() throws java.io.IOException {
byte[] array = new byte[4];
BufferedStream bs = NewBufferedStream(8, "abcdefghijkl");
assertEquals(true, bs.markSupported());
assertEquals(4, bs.read(array));
assertEquals("abcd", new String(array));
bs.mark(4);
assertEquals(4, bs.read(array));
assertEquals("efgh", new String(array));
bs.reset();
assertEquals(4, bs.read(array));
assertEquals("efgh", new String(array));
assertEquals(4, bs.read(array));
assertEquals("ijkl", new String(array));
assertEquals(-1, bs.read());
}
}

View File

@@ -0,0 +1,135 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import java.lang.reflect.InvocationTargetException;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.TypeTest.MyData;
import org.luaj.vm2.lib.ZeroArgFunction;
class LuaOperationsTest {
private final int sampleint = 77;
private final long samplelong = 123400000000L;
private final double sampledouble = 55.25;
private final String samplestringstring = "abcdef";
private final String samplestringint = String.valueOf(sampleint);
private final String samplestringlong = String.valueOf(samplelong);
private final String samplestringdouble = String.valueOf(sampledouble);
private final Object sampleobject = new Object();
private final MyData sampledata = new MyData();
private final LuaValue somenil = LuaValue.NIL;
private final LuaValue sometrue = LuaValue.TRUE;
private final LuaValue somefalse = LuaValue.FALSE;
private final LuaValue zero = LuaValue.ZERO;
private final LuaValue intint = LuaValue.valueOf(sampleint);
private final LuaValue longdouble = LuaValue.valueOf(samplelong);
private final LuaValue doubledouble = LuaValue.valueOf(sampledouble);
private final LuaValue stringstring = LuaValue.valueOf(samplestringstring);
private final LuaValue stringint = LuaValue.valueOf(samplestringint);
private final LuaValue stringlong = LuaValue.valueOf(samplestringlong);
private final LuaValue stringdouble = LuaValue.valueOf(samplestringdouble);
private final LuaTable table = LuaValue
.listOf(new LuaValue[] { LuaValue.valueOf("aaa"), LuaValue.valueOf("bbb") });
private final LuaValue somefunc = new ZeroArgFunction() {
@Override
public LuaValue call() { return NONE; }
};
private final LuaThread thread = new LuaThread(new Globals(), somefunc);
private final Prototype proto = new Prototype(1);
private final LuaClosure someclosure = new LuaClosure(proto, table);
private final LuaUserdata userdataobj = LuaValue.userdataOf(sampleobject);
private final LuaUserdata userdatacls = LuaValue.userdataOf(sampledata);
private void throwsLuaError(String methodName, Object obj) {
try {
LuaValue.class.getMethod(methodName).invoke(obj);
fail("failed to throw LuaError as required");
} catch (InvocationTargetException e) {
if (!(e.getTargetException() instanceof LuaError))
fail("not a LuaError: " + e.getTargetException());
return; // pass
} catch (Exception e) {
fail("bad exception: " + e);
}
}
private void throwsLuaError(String methodName, Object obj, Object arg) {
try {
LuaValue.class.getMethod(methodName, LuaValue.class).invoke(obj, arg);
fail("failed to throw LuaError as required");
} catch (InvocationTargetException e) {
if (!(e.getTargetException() instanceof LuaError))
fail("not a LuaError: " + e.getTargetException());
return; // pass
} catch (Exception e) {
fail("bad exception: " + e);
}
}
@Test
void testLen() {
throwsLuaError("len", somenil);
throwsLuaError("len", sometrue);
throwsLuaError("len", somefalse);
throwsLuaError("len", zero);
throwsLuaError("len", intint);
throwsLuaError("len", longdouble);
throwsLuaError("len", doubledouble);
assertEquals(LuaInteger.valueOf(samplestringstring.length()), stringstring.len());
assertEquals(LuaInteger.valueOf(samplestringint.length()), stringint.len());
assertEquals(LuaInteger.valueOf(samplestringlong.length()), stringlong.len());
assertEquals(LuaInteger.valueOf(samplestringdouble.length()), stringdouble.len());
assertEquals(LuaInteger.valueOf(2), table.len());
throwsLuaError("len", somefunc);
throwsLuaError("len", thread);
throwsLuaError("len", someclosure);
throwsLuaError("len", userdataobj);
throwsLuaError("len", userdatacls);
}
@Test
void testLength() {
throwsLuaError("length", somenil);
throwsLuaError("length", sometrue);
throwsLuaError("length", somefalse);
throwsLuaError("length", zero);
throwsLuaError("length", intint);
throwsLuaError("length", longdouble);
throwsLuaError("length", doubledouble);
assertEquals(samplestringstring.length(), stringstring.length());
assertEquals(samplestringint.length(), stringint.length());
assertEquals(samplestringlong.length(), stringlong.length());
assertEquals(samplestringdouble.length(), stringdouble.length());
assertEquals(2, table.length());
throwsLuaError("length", somefunc);
throwsLuaError("length", thread);
throwsLuaError("length", someclosure);
throwsLuaError("length", userdataobj);
throwsLuaError("length", userdatacls);
}
}

View File

@@ -0,0 +1,372 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.TypeTest.MyData;
import org.luaj.vm2.lib.StringLib;
import org.luaj.vm2.lib.ThreeArgFunction;
import org.luaj.vm2.lib.TwoArgFunction;
import org.luaj.vm2.lib.ZeroArgFunction;
class MetatableTest {
private final String samplestring = "abcdef";
private final Object sampleobject = new Object();
private final MyData sampledata = new MyData();
private final LuaValue string = LuaValue.valueOf(samplestring);
private final LuaTable table = LuaValue.tableOf();
private final LuaFunction function = new ZeroArgFunction() {
@Override
public LuaValue call() { return NONE; }
};
private final LuaThread thread = new LuaThread(new Globals(), function);
private final LuaClosure closure = new LuaClosure(new Prototype(), new LuaTable());
private final LuaUserdata userdata = LuaValue.userdataOf(sampleobject);
private final LuaUserdata userdatamt = LuaValue.userdataOf(sampledata, table);
@BeforeEach
protected void setUp() throws Exception {
// needed for metatable ops to work on strings
new StringLib();
}
@AfterEach
protected void tearDown() throws Exception {
LuaBoolean.s_metatable = null;
LuaFunction.s_metatable = null;
LuaNil.s_metatable = null;
LuaNumber.s_metatable = null;
// LuaString.s_metatable = null;
LuaThread.s_metatable = null;
}
@Test
void testGetMetatable() {
assertEquals(null, LuaValue.NIL.getmetatable());
assertEquals(null, LuaValue.TRUE.getmetatable());
assertEquals(null, LuaValue.ONE.getmetatable());
// assertEquals( null, string.getmetatable() );
assertEquals(null, table.getmetatable());
assertEquals(null, function.getmetatable());
assertEquals(null, thread.getmetatable());
assertEquals(null, closure.getmetatable());
assertEquals(null, userdata.getmetatable());
assertEquals(table, userdatamt.getmetatable());
}
@Test
void testSetMetatable() {
LuaValue mt = LuaValue.tableOf();
assertEquals(null, table.getmetatable());
assertEquals(null, userdata.getmetatable());
assertEquals(table, userdatamt.getmetatable());
assertEquals(table, table.setmetatable(mt));
assertEquals(userdata, userdata.setmetatable(mt));
assertEquals(userdatamt, userdatamt.setmetatable(mt));
assertEquals(mt, table.getmetatable());
assertEquals(mt, userdata.getmetatable());
assertEquals(mt, userdatamt.getmetatable());
// these all get metatable behind-the-scenes
assertEquals(null, LuaValue.NIL.getmetatable());
assertEquals(null, LuaValue.TRUE.getmetatable());
assertEquals(null, LuaValue.ONE.getmetatable());
// assertEquals( null, string.getmetatable() );
assertEquals(null, function.getmetatable());
assertEquals(null, thread.getmetatable());
assertEquals(null, closure.getmetatable());
LuaNil.s_metatable = mt;
assertEquals(mt, LuaValue.NIL.getmetatable());
assertEquals(null, LuaValue.TRUE.getmetatable());
assertEquals(null, LuaValue.ONE.getmetatable());
// assertEquals( null, string.getmetatable() );
assertEquals(null, function.getmetatable());
assertEquals(null, thread.getmetatable());
assertEquals(null, closure.getmetatable());
LuaBoolean.s_metatable = mt;
assertEquals(mt, LuaValue.TRUE.getmetatable());
assertEquals(null, LuaValue.ONE.getmetatable());
// assertEquals( null, string.getmetatable() );
assertEquals(null, function.getmetatable());
assertEquals(null, thread.getmetatable());
assertEquals(null, closure.getmetatable());
LuaNumber.s_metatable = mt;
assertEquals(mt, LuaValue.ONE.getmetatable());
assertEquals(mt, LuaValue.valueOf(1.25).getmetatable());
// assertEquals( null, string.getmetatable() );
assertEquals(null, function.getmetatable());
assertEquals(null, thread.getmetatable());
assertEquals(null, closure.getmetatable());
// LuaString.s_metatable = mt;
// assertEquals( mt, string.getmetatable() );
assertEquals(null, function.getmetatable());
assertEquals(null, thread.getmetatable());
assertEquals(null, closure.getmetatable());
LuaFunction.s_metatable = mt;
assertEquals(mt, function.getmetatable());
assertEquals(null, thread.getmetatable());
LuaThread.s_metatable = mt;
assertEquals(mt, thread.getmetatable());
}
@Test
void testMetatableIndex() {
assertEquals(table, table.setmetatable(null));
assertEquals(userdata, userdata.setmetatable(null));
assertEquals(userdatamt, userdatamt.setmetatable(null));
assertEquals(LuaValue.NIL, table.get(1));
assertEquals(LuaValue.NIL, userdata.get(1));
assertEquals(LuaValue.NIL, userdatamt.get(1));
// empty metatable
LuaValue mt = LuaValue.tableOf();
assertEquals(table, table.setmetatable(mt));
assertEquals(userdata, userdata.setmetatable(mt));
LuaBoolean.s_metatable = mt;
LuaFunction.s_metatable = mt;
LuaNil.s_metatable = mt;
LuaNumber.s_metatable = mt;
// LuaString.s_metatable = mt;
LuaThread.s_metatable = mt;
assertEquals(mt, table.getmetatable());
assertEquals(mt, userdata.getmetatable());
assertEquals(mt, LuaValue.NIL.getmetatable());
assertEquals(mt, LuaValue.TRUE.getmetatable());
assertEquals(mt, LuaValue.ONE.getmetatable());
// assertEquals( StringLib.instance, string.getmetatable() );
assertEquals(mt, function.getmetatable());
assertEquals(mt, thread.getmetatable());
// plain metatable
LuaValue abc = LuaValue.valueOf("abc");
mt.set(LuaValue.INDEX, LuaValue.listOf(new LuaValue[] { abc }));
assertEquals(abc, table.get(1));
assertEquals(abc, userdata.get(1));
assertEquals(abc, LuaValue.NIL.get(1));
assertEquals(abc, LuaValue.TRUE.get(1));
assertEquals(abc, LuaValue.ONE.get(1));
// assertEquals( abc, string.get(1) );
assertEquals(abc, function.get(1));
assertEquals(abc, thread.get(1));
// plain metatable
mt.set(LuaValue.INDEX, new TwoArgFunction() {
@Override
public LuaValue call(LuaValue arg1, LuaValue arg2) {
return LuaValue.valueOf(arg1.typename() + "[" + arg2.tojstring() + "]=xyz");
}
});
assertEquals("table[1]=xyz", table.get(1).tojstring());
assertEquals("userdata[1]=xyz", userdata.get(1).tojstring());
assertEquals("nil[1]=xyz", LuaValue.NIL.get(1).tojstring());
assertEquals("boolean[1]=xyz", LuaValue.TRUE.get(1).tojstring());
assertEquals("number[1]=xyz", LuaValue.ONE.get(1).tojstring());
// assertEquals( "string[1]=xyz", string.get(1).tojstring() );
assertEquals("function[1]=xyz", function.get(1).tojstring());
assertEquals("thread[1]=xyz", thread.get(1).tojstring());
}
@Test
void testMetatableNewIndex() {
// empty metatable
LuaValue mt = LuaValue.tableOf();
assertEquals(table, table.setmetatable(mt));
assertEquals(userdata, userdata.setmetatable(mt));
LuaBoolean.s_metatable = mt;
LuaFunction.s_metatable = mt;
LuaNil.s_metatable = mt;
LuaNumber.s_metatable = mt;
// LuaString.s_metatable = mt;
LuaThread.s_metatable = mt;
// plain metatable
final LuaValue fallback = LuaValue.tableOf();
LuaValue abc = LuaValue.valueOf("abc");
mt.set(LuaValue.NEWINDEX, fallback);
table.set(2, abc);
userdata.set(3, abc);
LuaValue.NIL.set(4, abc);
LuaValue.TRUE.set(5, abc);
LuaValue.ONE.set(6, abc);
// string.set(7,abc);
function.set(8, abc);
thread.set(9, abc);
assertEquals(abc, fallback.get(2));
assertEquals(abc, fallback.get(3));
assertEquals(abc, fallback.get(4));
assertEquals(abc, fallback.get(5));
assertEquals(abc, fallback.get(6));
// assertEquals( abc, StringLib.instance.get(7) );
assertEquals(abc, fallback.get(8));
assertEquals(abc, fallback.get(9));
// metatable with function call
mt.set(LuaValue.NEWINDEX, new ThreeArgFunction() {
@Override
public LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) {
fallback.rawset(arg2, LuaValue.valueOf("via-func-" + arg3));
return NONE;
}
});
table.set(12, abc);
userdata.set(13, abc);
LuaValue.NIL.set(14, abc);
LuaValue.TRUE.set(15, abc);
LuaValue.ONE.set(16, abc);
// string.set(17,abc);
function.set(18, abc);
thread.set(19, abc);
LuaValue via = LuaValue.valueOf("via-func-abc");
assertEquals(via, fallback.get(12));
assertEquals(via, fallback.get(13));
assertEquals(via, fallback.get(14));
assertEquals(via, fallback.get(15));
assertEquals(via, fallback.get(16));
// assertEquals( via, StringLib.instance.get(17) );
assertEquals(via, fallback.get(18));
assertEquals(via, fallback.get(19));
}
private void checkTable(LuaValue t, LuaValue aa, LuaValue bb, LuaValue cc, LuaValue dd, LuaValue ee, LuaValue ff,
LuaValue gg, LuaValue ra, LuaValue rb, LuaValue rc, LuaValue rd, LuaValue re, LuaValue rf, LuaValue rg) {
assertEquals(aa, t.get("aa"));
assertEquals(bb, t.get("bb"));
assertEquals(cc, t.get("cc"));
assertEquals(dd, t.get("dd"));
assertEquals(ee, t.get("ee"));
assertEquals(ff, t.get("ff"));
assertEquals(gg, t.get("gg"));
assertEquals(ra, t.rawget("aa"));
assertEquals(rb, t.rawget("bb"));
assertEquals(rc, t.rawget("cc"));
assertEquals(rd, t.rawget("dd"));
assertEquals(re, t.rawget("ee"));
assertEquals(rf, t.rawget("ff"));
assertEquals(rg, t.rawget("gg"));
}
private LuaValue makeTable(String key1, String val1, String key2, String val2) {
return LuaValue.tableOf(new LuaValue[] { LuaValue.valueOf(key1), LuaValue.valueOf(val1), LuaValue.valueOf(key2),
LuaValue.valueOf(val2), });
}
@Test
void testRawsetMetatableSet() {
// set up tables
LuaValue m = makeTable("aa", "aaa", "bb", "bbb");
m.set(LuaValue.INDEX, m);
m.set(LuaValue.NEWINDEX, m);
LuaValue s = makeTable("cc", "ccc", "dd", "ddd");
LuaValue t = makeTable("cc", "ccc", "dd", "ddd");
t.setmetatable(m);
LuaValue aaa = LuaValue.valueOf("aaa");
LuaValue bbb = LuaValue.valueOf("bbb");
LuaValue ccc = LuaValue.valueOf("ccc");
LuaValue ddd = LuaValue.valueOf("ddd");
LuaValue ppp = LuaValue.valueOf("ppp");
LuaValue qqq = LuaValue.valueOf("qqq");
LuaValue rrr = LuaValue.valueOf("rrr");
LuaValue sss = LuaValue.valueOf("sss");
LuaValue ttt = LuaValue.valueOf("ttt");
LuaValue www = LuaValue.valueOf("www");
LuaValue xxx = LuaValue.valueOf("xxx");
LuaValue yyy = LuaValue.valueOf("yyy");
LuaValue zzz = LuaValue.valueOf("zzz");
LuaValue nil = LuaValue.NIL;
// check initial values
// values via "bet()" values via "rawget()"
checkTable(s, nil, nil, ccc, ddd, nil, nil, nil, nil, nil, ccc, ddd, nil, nil, nil);
checkTable(t, aaa, bbb, ccc, ddd, nil, nil, nil, nil, nil, ccc, ddd, nil, nil, nil);
checkTable(m, aaa, bbb, nil, nil, nil, nil, nil, aaa, bbb, nil, nil, nil, nil, nil);
// rawset()
s.rawset("aa", www);
checkTable(s, www, nil, ccc, ddd, nil, nil, nil, www, nil, ccc, ddd, nil, nil, nil);
checkTable(t, aaa, bbb, ccc, ddd, nil, nil, nil, nil, nil, ccc, ddd, nil, nil, nil);
checkTable(m, aaa, bbb, nil, nil, nil, nil, nil, aaa, bbb, nil, nil, nil, nil, nil);
s.rawset("cc", xxx);
checkTable(s, www, nil, xxx, ddd, nil, nil, nil, www, nil, xxx, ddd, nil, nil, nil);
checkTable(t, aaa, bbb, ccc, ddd, nil, nil, nil, nil, nil, ccc, ddd, nil, nil, nil);
checkTable(m, aaa, bbb, nil, nil, nil, nil, nil, aaa, bbb, nil, nil, nil, nil, nil);
t.rawset("bb", yyy);
checkTable(s, www, nil, xxx, ddd, nil, nil, nil, www, nil, xxx, ddd, nil, nil, nil);
checkTable(t, aaa, yyy, ccc, ddd, nil, nil, nil, nil, yyy, ccc, ddd, nil, nil, nil);
checkTable(m, aaa, bbb, nil, nil, nil, nil, nil, aaa, bbb, nil, nil, nil, nil, nil);
t.rawset("dd", zzz);
checkTable(s, www, nil, xxx, ddd, nil, nil, nil, www, nil, xxx, ddd, nil, nil, nil);
checkTable(t, aaa, yyy, ccc, zzz, nil, nil, nil, nil, yyy, ccc, zzz, nil, nil, nil);
checkTable(m, aaa, bbb, nil, nil, nil, nil, nil, aaa, bbb, nil, nil, nil, nil, nil);
// set() invoking metatables
s.set("ee", ppp);
checkTable(s, www, nil, xxx, ddd, ppp, nil, nil, www, nil, xxx, ddd, ppp, nil, nil);
checkTable(t, aaa, yyy, ccc, zzz, nil, nil, nil, nil, yyy, ccc, zzz, nil, nil, nil);
checkTable(m, aaa, bbb, nil, nil, nil, nil, nil, aaa, bbb, nil, nil, nil, nil, nil);
s.set("cc", qqq);
checkTable(s, www, nil, qqq, ddd, ppp, nil, nil, www, nil, qqq, ddd, ppp, nil, nil);
checkTable(t, aaa, yyy, ccc, zzz, nil, nil, nil, nil, yyy, ccc, zzz, nil, nil, nil);
checkTable(m, aaa, bbb, nil, nil, nil, nil, nil, aaa, bbb, nil, nil, nil, nil, nil);
t.set("ff", rrr);
checkTable(s, www, nil, qqq, ddd, ppp, nil, nil, www, nil, qqq, ddd, ppp, nil, nil);
checkTable(t, aaa, yyy, ccc, zzz, nil, rrr, nil, nil, yyy, ccc, zzz, nil, nil, nil);
checkTable(m, aaa, bbb, nil, nil, nil, rrr, nil, aaa, bbb, nil, nil, nil, rrr, nil);
t.set("dd", sss);
checkTable(s, www, nil, qqq, ddd, ppp, nil, nil, www, nil, qqq, ddd, ppp, nil, nil);
checkTable(t, aaa, yyy, ccc, sss, nil, rrr, nil, nil, yyy, ccc, sss, nil, nil, nil);
checkTable(m, aaa, bbb, nil, nil, nil, rrr, nil, aaa, bbb, nil, nil, nil, rrr, nil);
m.set("gg", ttt);
checkTable(s, www, nil, qqq, ddd, ppp, nil, nil, www, nil, qqq, ddd, ppp, nil, nil);
checkTable(t, aaa, yyy, ccc, sss, nil, rrr, ttt, nil, yyy, ccc, sss, nil, nil, nil);
checkTable(m, aaa, bbb, nil, nil, nil, rrr, ttt, aaa, bbb, nil, nil, nil, rrr, ttt);
// make s fall back to t
s.setmetatable(LuaValue.tableOf(new LuaValue[] { LuaValue.INDEX, t, LuaValue.NEWINDEX, t }));
checkTable(s, www, yyy, qqq, ddd, ppp, rrr, ttt, www, nil, qqq, ddd, ppp, nil, nil);
checkTable(t, aaa, yyy, ccc, sss, nil, rrr, ttt, nil, yyy, ccc, sss, nil, nil, nil);
checkTable(m, aaa, bbb, nil, nil, nil, rrr, ttt, aaa, bbb, nil, nil, nil, rrr, ttt);
s.set("aa", www);
checkTable(s, www, yyy, qqq, ddd, ppp, rrr, ttt, www, nil, qqq, ddd, ppp, nil, nil);
checkTable(t, aaa, yyy, ccc, sss, nil, rrr, ttt, nil, yyy, ccc, sss, nil, nil, nil);
checkTable(m, aaa, bbb, nil, nil, nil, rrr, ttt, aaa, bbb, nil, nil, nil, rrr, ttt);
s.set("bb", zzz);
checkTable(s, www, zzz, qqq, ddd, ppp, rrr, ttt, www, nil, qqq, ddd, ppp, nil, nil);
checkTable(t, aaa, zzz, ccc, sss, nil, rrr, ttt, nil, zzz, ccc, sss, nil, nil, nil);
checkTable(m, aaa, bbb, nil, nil, nil, rrr, ttt, aaa, bbb, nil, nil, nil, rrr, ttt);
s.set("ee", xxx);
checkTable(s, www, zzz, qqq, ddd, xxx, rrr, ttt, www, nil, qqq, ddd, xxx, nil, nil);
checkTable(t, aaa, zzz, ccc, sss, nil, rrr, ttt, nil, zzz, ccc, sss, nil, nil, nil);
checkTable(m, aaa, bbb, nil, nil, nil, rrr, ttt, aaa, bbb, nil, nil, nil, rrr, ttt);
s.set("ff", yyy);
checkTable(s, www, zzz, qqq, ddd, xxx, yyy, ttt, www, nil, qqq, ddd, xxx, nil, nil);
checkTable(t, aaa, zzz, ccc, sss, nil, yyy, ttt, nil, zzz, ccc, sss, nil, nil, nil);
checkTable(m, aaa, bbb, nil, nil, nil, yyy, ttt, aaa, bbb, nil, nil, nil, yyy, ttt);
}
}

View File

@@ -0,0 +1,368 @@
package org.luaj.vm2;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import org.junit.jupiter.api.Test;
class StringTest {
@Test
void testToInputStream() throws IOException {
LuaString str = LuaString.valueOf("Hello");
InputStream is = str.toInputStream();
assertEquals('H', is.read());
assertEquals('e', is.read());
assertEquals(2, is.skip(2));
assertEquals('o', is.read());
assertEquals(-1, is.read());
assertTrue(is.markSupported());
is.reset();
assertEquals('H', is.read());
is.mark(4);
assertEquals('e', is.read());
is.reset();
assertEquals('e', is.read());
LuaString substr = str.substring(1, 4);
assertEquals(3, substr.length());
is.close();
is = substr.toInputStream();
assertEquals('e', is.read());
assertEquals('l', is.read());
assertEquals('l', is.read());
assertEquals(-1, is.read());
is = substr.toInputStream();
is.reset();
assertEquals('e', is.read());
}
private static final String userFriendly(String s) {
StringBuffer sb = new StringBuffer();
for (int i = 0, n = s.length(); i < n; i++) {
int c = s.charAt(i);
if (c < ' ' || c >= 0x80) {
sb.append("\\u" + Integer.toHexString(0x10000+c).substring(1));
} else {
sb.append((char) c);
}
}
return sb.toString();
}
@Test
void testUtf820482051() throws UnsupportedEncodingException {
int i = 2048;
char[] c = { (char) (i+0), (char) (i+1), (char) (i+2), (char) (i+3) };
String before = new String(c) + " " + i + "-" + (i+4);
LuaString ls = LuaString.valueOf(before);
String after = ls.tojstring();
assertEquals(userFriendly(before), userFriendly(after));
}
@Test
void testUtf8() {
for (int i = 4; i < 0xffff; i += 4) {
char[] c = { (char) (i+0), (char) (i+1), (char) (i+2), (char) (i+3) };
String before = new String(c) + " " + i + "-" + (i+4);
LuaString ls = LuaString.valueOf(before);
String after = ls.tojstring();
assertEquals(userFriendly(before), userFriendly(after));
}
char[] c = { (char) (1), (char) (2), (char) (3) };
String before = new String(c) + " 1-3";
LuaString ls = LuaString.valueOf(before);
String after = ls.tojstring();
assertEquals(userFriendly(before), userFriendly(after));
}
@Test
void testSpotCheckUtf8() throws UnsupportedEncodingException {
byte[] bytes = { (byte) 194, (byte) 160, (byte) 194, (byte) 161, (byte) 194, (byte) 162, (byte) 194, (byte) 163,
(byte) 194, (byte) 164 };
String expected = new String(bytes, "UTF8");
String actual = LuaString.valueOf(bytes).tojstring();
char[] d = actual.toCharArray();
assertEquals(160, d[0]);
assertEquals(161, d[1]);
assertEquals(162, d[2]);
assertEquals(163, d[3]);
assertEquals(164, d[4]);
assertEquals(expected, actual);
}
@Test
void testNullTerminated() {
char[] c = { 'a', 'b', 'c', '\0', 'd', 'e', 'f' };
String before = new String(c);
LuaString ls = LuaString.valueOf(before);
String after = ls.tojstring();
assertEquals(userFriendly("abc\0def"), userFriendly(after));
}
@Test
void testRecentStringsCacheDifferentHashcodes() {
final byte[] abc = { 'a', 'b', 'c' };
final byte[] xyz = { 'x', 'y', 'z' };
final LuaString abc1 = LuaString.valueOf(abc);
final LuaString xyz1 = LuaString.valueOf(xyz);
final LuaString abc2 = LuaString.valueOf(abc);
final LuaString xyz2 = LuaString.valueOf(xyz);
final int mod = LuaString.RECENT_STRINGS_CACHE_SIZE;
assertTrue(abc1.hashCode()%mod != xyz1.hashCode()%mod);
assertSame(abc1, abc2);
assertSame(xyz1, xyz2);
}
@Test
void testRecentStringsCacheHashCollisionCacheHit() {
final byte[] abc = { 'a', 'b', 'c' };
final byte[] lyz = { 'l', 'y', 'z' }; // chosen to have hash collision with 'abc'
final LuaString abc1 = LuaString.valueOf(abc);
final LuaString abc2 = LuaString.valueOf(abc); // in cache: 'abc'
final LuaString lyz1 = LuaString.valueOf(lyz);
final LuaString lyz2 = LuaString.valueOf(lyz); // in cache: 'lyz'
final int mod = LuaString.RECENT_STRINGS_CACHE_SIZE;
assertEquals(abc1.hashCode()%mod, lyz1.hashCode()%mod);
assertNotSame(abc1, lyz1);
assertFalse(abc1.equals(lyz1));
assertSame(abc1, abc2);
assertSame(lyz1, lyz2);
}
@Test
void testRecentStringsCacheHashCollisionCacheMiss() {
final byte[] abc = { 'a', 'b', 'c' };
final byte[] lyz = { 'l', 'y', 'z' }; // chosen to have hash collision with 'abc'
final LuaString abc1 = LuaString.valueOf(abc);
final LuaString lyz1 = LuaString.valueOf(lyz); // in cache: 'abc'
final LuaString abc2 = LuaString.valueOf(abc); // in cache: 'lyz'
final LuaString lyz2 = LuaString.valueOf(lyz); // in cache: 'abc'
final int mod = LuaString.RECENT_STRINGS_CACHE_SIZE;
assertEquals(abc1.hashCode()%mod, lyz1.hashCode()%mod);
assertNotSame(abc1, lyz1);
assertFalse(abc1.equals(lyz1));
assertNotSame(abc1, abc2);
assertNotSame(lyz1, lyz2);
}
@Test
void testRecentStringsLongStrings() {
byte[] abc = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes();
assertTrue(abc.length > LuaString.RECENT_STRINGS_MAX_LENGTH);
LuaString abc1 = LuaString.valueOf(abc);
LuaString abc2 = LuaString.valueOf(abc);
assertNotSame(abc1, abc2);
}
@Test
void testRecentStringsUsingJavaStrings() {
final String abc = "abc";
final String lyz = "lyz"; // chosen to have hash collision with 'abc'
final String xyz = "xyz";
final LuaString abc1 = LuaString.valueOf(abc);
final LuaString abc2 = LuaString.valueOf(abc);
final LuaString lyz1 = LuaString.valueOf(lyz);
final LuaString lyz2 = LuaString.valueOf(lyz);
final LuaString xyz1 = LuaString.valueOf(xyz);
final LuaString xyz2 = LuaString.valueOf(xyz);
final int mod = LuaString.RECENT_STRINGS_CACHE_SIZE;
assertEquals(abc1.hashCode()%mod, lyz1.hashCode()%mod);
assertFalse(abc1.hashCode()%mod == xyz1.hashCode()%mod);
assertSame(abc1, abc2);
assertSame(lyz1, lyz2);
assertSame(xyz1, xyz2);
final LuaString abc3 = LuaString.valueOf(abc);
final LuaString lyz3 = LuaString.valueOf(lyz);
final LuaString xyz3 = LuaString.valueOf(xyz);
final LuaString abc4 = LuaString.valueOf(abc);
final LuaString lyz4 = LuaString.valueOf(lyz);
final LuaString xyz4 = LuaString.valueOf(xyz);
assertNotSame(abc3, abc4); // because of hash collision
assertNotSame(lyz3, lyz4); // because of hash collision
assertSame(xyz3, xyz4); // because hashes do not collide
}
@Test
void testLongSubstringGetsOldBacking() {
LuaString src = LuaString.valueOf("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
LuaString sub1 = src.substring(10, 40);
assertSame(src.m_bytes, sub1.m_bytes);
assertEquals(sub1.m_offset, 10);
assertEquals(sub1.m_length, 30);
}
@Test
void testShortSubstringGetsNewBacking() {
LuaString src = LuaString.valueOf("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
LuaString sub1 = src.substring(10, 20);
LuaString sub2 = src.substring(10, 20);
assertEquals(sub1.m_offset, 0);
assertEquals(sub1.m_length, 10);
assertSame(sub1, sub2);
assertFalse(src.m_bytes == sub1.m_bytes);
}
@Test
void testShortSubstringOfVeryLongStringGetsNewBacking() {
LuaString src = LuaString.valueOf("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
LuaString sub1 = src.substring(10, 50);
LuaString sub2 = src.substring(10, 50);
assertEquals(sub1.m_offset, 0);
assertEquals(sub1.m_length, 40);
assertFalse(sub1 == sub2);
assertFalse(src.m_bytes == sub1.m_bytes);
}
@Test
void testIndexOfByteInSubstring() {
LuaString str = LuaString.valueOf("abcdef:ghi");
LuaString sub = str.substring(2, 10);
assertEquals(10, str.m_length);
assertEquals(8, sub.m_length);
assertEquals(0, str.m_offset);
assertEquals(2, sub.m_offset);
assertEquals(6, str.indexOf((byte) ':', 0));
assertEquals(6, str.indexOf((byte) ':', 2));
assertEquals(6, str.indexOf((byte) ':', 6));
assertEquals(-1, str.indexOf((byte) ':', 7));
assertEquals(-1, str.indexOf((byte) ':', 9));
assertEquals(9, str.indexOf((byte) 'i', 0));
assertEquals(9, str.indexOf((byte) 'i', 2));
assertEquals(9, str.indexOf((byte) 'i', 9));
assertEquals(-1, str.indexOf((byte) 'z', 0));
assertEquals(-1, str.indexOf((byte) 'z', 2));
assertEquals(-1, str.indexOf((byte) 'z', 9));
assertEquals(4, sub.indexOf((byte) ':', 0));
assertEquals(4, sub.indexOf((byte) ':', 2));
assertEquals(4, sub.indexOf((byte) ':', 4));
assertEquals(-1, sub.indexOf((byte) ':', 5));
assertEquals(-1, sub.indexOf((byte) ':', 7));
assertEquals(7, sub.indexOf((byte) 'i', 0));
assertEquals(7, sub.indexOf((byte) 'i', 2));
assertEquals(7, sub.indexOf((byte) 'i', 7));
assertEquals(-1, sub.indexOf((byte) 'z', 0));
assertEquals(-1, sub.indexOf((byte) 'z', 2));
assertEquals(-1, sub.indexOf((byte) 'z', 7));
}
@Test
void testIndexOfPatternInSubstring() {
LuaString str = LuaString.valueOf("abcdef:ghi");
LuaString sub = str.substring(2, 10);
assertEquals(10, str.m_length);
assertEquals(8, sub.m_length);
assertEquals(0, str.m_offset);
assertEquals(2, sub.m_offset);
LuaString pat = LuaString.valueOf(":");
LuaString i = LuaString.valueOf("i");
LuaString xyz = LuaString.valueOf("xyz");
assertEquals(6, str.indexOf(pat, 0));
assertEquals(6, str.indexOf(pat, 2));
assertEquals(6, str.indexOf(pat, 6));
assertEquals(-1, str.indexOf(pat, 7));
assertEquals(-1, str.indexOf(pat, 9));
assertEquals(9, str.indexOf(i, 0));
assertEquals(9, str.indexOf(i, 2));
assertEquals(9, str.indexOf(i, 9));
assertEquals(-1, str.indexOf(xyz, 0));
assertEquals(-1, str.indexOf(xyz, 2));
assertEquals(-1, str.indexOf(xyz, 9));
assertEquals(4, sub.indexOf(pat, 0));
assertEquals(4, sub.indexOf(pat, 2));
assertEquals(4, sub.indexOf(pat, 4));
assertEquals(-1, sub.indexOf(pat, 5));
assertEquals(-1, sub.indexOf(pat, 7));
assertEquals(7, sub.indexOf(i, 0));
assertEquals(7, sub.indexOf(i, 2));
assertEquals(7, sub.indexOf(i, 7));
assertEquals(-1, sub.indexOf(xyz, 0));
assertEquals(-1, sub.indexOf(xyz, 2));
assertEquals(-1, sub.indexOf(xyz, 7));
}
@Test
void testLastIndexOfPatternInSubstring() {
LuaString str = LuaString.valueOf("abcdef:ghi");
LuaString sub = str.substring(2, 10);
assertEquals(10, str.m_length);
assertEquals(8, sub.m_length);
assertEquals(0, str.m_offset);
assertEquals(2, sub.m_offset);
LuaString pat = LuaString.valueOf(":");
LuaString i = LuaString.valueOf("i");
LuaString xyz = LuaString.valueOf("xyz");
assertEquals(6, str.lastIndexOf(pat));
assertEquals(9, str.lastIndexOf(i));
assertEquals(-1, str.lastIndexOf(xyz));
assertEquals(4, sub.lastIndexOf(pat));
assertEquals(7, sub.lastIndexOf(i));
assertEquals(-1, sub.lastIndexOf(xyz));
}
@Test
void testIndexOfAnyInSubstring() {
LuaString str = LuaString.valueOf("abcdef:ghi");
LuaString sub = str.substring(2, 10);
assertEquals(10, str.m_length);
assertEquals(8, sub.m_length);
assertEquals(0, str.m_offset);
assertEquals(2, sub.m_offset);
LuaString ghi = LuaString.valueOf("ghi");
LuaString ihg = LuaString.valueOf("ihg");
LuaString ijk = LuaString.valueOf("ijk");
LuaString kji = LuaString.valueOf("kji");
LuaString xyz = LuaString.valueOf("xyz");
LuaString ABCdEFGHIJKL = LuaString.valueOf("ABCdEFGHIJKL");
LuaString EFGHIJKL = ABCdEFGHIJKL.substring(4, 12);
LuaString CdEFGHIJ = ABCdEFGHIJKL.substring(2, 10);
assertEquals(4, EFGHIJKL.m_offset);
assertEquals(2, CdEFGHIJ.m_offset);
assertEquals(7, str.indexOfAny(ghi));
assertEquals(7, str.indexOfAny(ihg));
assertEquals(9, str.indexOfAny(ijk));
assertEquals(9, str.indexOfAny(kji));
assertEquals(-1, str.indexOfAny(xyz));
assertEquals(3, str.indexOfAny(CdEFGHIJ));
assertEquals(-1, str.indexOfAny(EFGHIJKL));
assertEquals(5, sub.indexOfAny(ghi));
assertEquals(5, sub.indexOfAny(ihg));
assertEquals(7, sub.indexOfAny(ijk));
assertEquals(7, sub.indexOfAny(kji));
assertEquals(-1, sub.indexOfAny(xyz));
assertEquals(1, sub.indexOfAny(CdEFGHIJ));
assertEquals(-1, sub.indexOfAny(EFGHIJKL));
}
}

View File

@@ -0,0 +1,325 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
import org.luaj.vm2.lib.TwoArgFunction;
/**
* Tests for tables used as lists.
*/
public class TableHashTest {
protected LuaTable new_Table() {
return new LuaTable();
}
protected LuaTable new_Table(int n, int m) {
return new LuaTable(n, m);
}
@Test
void testSetRemove() {
LuaTable t = new_Table();
assertEquals(0, t.getHashLength());
assertEquals(0, t.length());
assertEquals(0, t.keyCount());
String[] keys = { "abc", "def", "ghi", "jkl", "mno", "pqr", "stu", "wxy", "z01", "cd", "ef", "g", "hi", "jk",
"lm", "no", "pq", "rs", };
int[] capacities = { 0, 2, 2, 4, 4, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 32, 32, 32 };
for (int i = 0; i < keys.length; ++i) {
assertEquals(capacities[i], t.getHashLength());
String si = "Test Value! " + i;
t.set(keys[i], si);
assertEquals(0, t.length());
assertEquals(i+1, t.keyCount());
}
assertEquals(capacities[keys.length], t.getHashLength());
for (int i = 0; i < keys.length; ++i) {
LuaValue vi = LuaString.valueOf("Test Value! " + i);
assertEquals(vi, t.get(keys[i]));
assertEquals(vi, t.get(LuaString.valueOf(keys[i])));
assertEquals(vi, t.rawget(keys[i]));
assertEquals(vi, t.rawget(keys[i]));
}
// replace with new values
for (int i = 0; i < keys.length; ++i) {
t.set(keys[i], LuaString.valueOf("Replacement Value! " + i));
assertEquals(0, t.length());
assertEquals(keys.length, t.keyCount());
assertEquals(capacities[keys.length], t.getHashLength());
}
for (int i = 0; i < keys.length; ++i) {
LuaValue vi = LuaString.valueOf("Replacement Value! " + i);
assertEquals(vi, t.get(keys[i]));
}
// remove
for (int i = 0; i < keys.length; ++i) {
t.set(keys[i], LuaValue.NIL);
assertEquals(0, t.length());
assertEquals(keys.length-i-1, t.keyCount());
if (i < keys.length-1)
assertEquals(capacities[keys.length], t.getHashLength());
else
assertTrue(0 <= t.getHashLength());
}
for (int i = 0; i < keys.length; ++i) {
assertEquals(LuaValue.NIL, t.get(keys[i]));
}
}
@Test
void testIndexMetatag() {
LuaTable t = new_Table();
LuaTable mt = new_Table();
LuaTable fb = new_Table();
// set basic values
t.set("ppp", "abc");
t.set(123, "def");
mt.set(LuaValue.INDEX, fb);
fb.set("qqq", "ghi");
fb.set(456, "jkl");
// check before setting metatable
assertEquals("abc", t.get("ppp").tojstring());
assertEquals("def", t.get(123).tojstring());
assertEquals("nil", t.get("qqq").tojstring());
assertEquals("nil", t.get(456).tojstring());
assertEquals("nil", fb.get("ppp").tojstring());
assertEquals("nil", fb.get(123).tojstring());
assertEquals("ghi", fb.get("qqq").tojstring());
assertEquals("jkl", fb.get(456).tojstring());
assertEquals("nil", mt.get("ppp").tojstring());
assertEquals("nil", mt.get(123).tojstring());
assertEquals("nil", mt.get("qqq").tojstring());
assertEquals("nil", mt.get(456).tojstring());
// check before setting metatable
t.setmetatable(mt);
assertEquals(mt, t.getmetatable());
assertEquals("abc", t.get("ppp").tojstring());
assertEquals("def", t.get(123).tojstring());
assertEquals("ghi", t.get("qqq").tojstring());
assertEquals("jkl", t.get(456).tojstring());
assertEquals("nil", fb.get("ppp").tojstring());
assertEquals("nil", fb.get(123).tojstring());
assertEquals("ghi", fb.get("qqq").tojstring());
assertEquals("jkl", fb.get(456).tojstring());
assertEquals("nil", mt.get("ppp").tojstring());
assertEquals("nil", mt.get(123).tojstring());
assertEquals("nil", mt.get("qqq").tojstring());
assertEquals("nil", mt.get(456).tojstring());
// set metatable to metatable without values
t.setmetatable(fb);
assertEquals("abc", t.get("ppp").tojstring());
assertEquals("def", t.get(123).tojstring());
assertEquals("nil", t.get("qqq").tojstring());
assertEquals("nil", t.get(456).tojstring());
// set metatable to null
t.setmetatable(null);
assertEquals("abc", t.get("ppp").tojstring());
assertEquals("def", t.get(123).tojstring());
assertEquals("nil", t.get("qqq").tojstring());
assertEquals("nil", t.get(456).tojstring());
}
@Test
void testIndexFunction() {
final LuaTable t = new_Table();
final LuaTable mt = new_Table();
final TwoArgFunction fb = new TwoArgFunction() {
@Override
public LuaValue call(LuaValue tbl, LuaValue key) {
assertEquals(tbl, t);
return valueOf("from mt: " + key);
}
};
// set basic values
t.set("ppp", "abc");
t.set(123, "def");
mt.set(LuaValue.INDEX, fb);
// check before setting metatable
assertEquals("abc", t.get("ppp").tojstring());
assertEquals("def", t.get(123).tojstring());
assertEquals("nil", t.get("qqq").tojstring());
assertEquals("nil", t.get(456).tojstring());
// check before setting metatable
t.setmetatable(mt);
assertEquals(mt, t.getmetatable());
assertEquals("abc", t.get("ppp").tojstring());
assertEquals("def", t.get(123).tojstring());
assertEquals("from mt: qqq", t.get("qqq").tojstring());
assertEquals("from mt: 456", t.get(456).tojstring());
// use raw set
t.rawset("qqq", "alt-qqq");
t.rawset(456, "alt-456");
assertEquals("abc", t.get("ppp").tojstring());
assertEquals("def", t.get(123).tojstring());
assertEquals("alt-qqq", t.get("qqq").tojstring());
assertEquals("alt-456", t.get(456).tojstring());
// remove using raw set
t.rawset("qqq", LuaValue.NIL);
t.rawset(456, LuaValue.NIL);
assertEquals("abc", t.get("ppp").tojstring());
assertEquals("def", t.get(123).tojstring());
assertEquals("from mt: qqq", t.get("qqq").tojstring());
assertEquals("from mt: 456", t.get(456).tojstring());
// set metatable to null
t.setmetatable(null);
assertEquals("abc", t.get("ppp").tojstring());
assertEquals("def", t.get(123).tojstring());
assertEquals("nil", t.get("qqq").tojstring());
assertEquals("nil", t.get(456).tojstring());
}
@Test
void testNext() {
final LuaTable t = new_Table();
assertEquals(LuaValue.NIL, t.next(LuaValue.NIL));
// insert array elements
t.set(1, "one");
assertEquals(LuaValue.valueOf(1), t.next(LuaValue.NIL).arg(1));
assertEquals(LuaValue.valueOf("one"), t.next(LuaValue.NIL).arg(2));
assertEquals(LuaValue.NIL, t.next(LuaValue.ONE));
t.set(2, "two");
assertEquals(LuaValue.valueOf(1), t.next(LuaValue.NIL).arg(1));
assertEquals(LuaValue.valueOf("one"), t.next(LuaValue.NIL).arg(2));
assertEquals(LuaValue.valueOf(2), t.next(LuaValue.ONE).arg(1));
assertEquals(LuaValue.valueOf("two"), t.next(LuaValue.ONE).arg(2));
assertEquals(LuaValue.NIL, t.next(LuaValue.valueOf(2)));
// insert hash elements
t.set("aa", "aaa");
assertEquals(LuaValue.valueOf(1), t.next(LuaValue.NIL).arg(1));
assertEquals(LuaValue.valueOf("one"), t.next(LuaValue.NIL).arg(2));
assertEquals(LuaValue.valueOf(2), t.next(LuaValue.ONE).arg(1));
assertEquals(LuaValue.valueOf("two"), t.next(LuaValue.ONE).arg(2));
assertEquals(LuaValue.valueOf("aa"), t.next(LuaValue.valueOf(2)).arg(1));
assertEquals(LuaValue.valueOf("aaa"), t.next(LuaValue.valueOf(2)).arg(2));
assertEquals(LuaValue.NIL, t.next(LuaValue.valueOf("aa")));
t.set("bb", "bbb");
assertEquals(LuaValue.valueOf(1), t.next(LuaValue.NIL).arg(1));
assertEquals(LuaValue.valueOf("one"), t.next(LuaValue.NIL).arg(2));
assertEquals(LuaValue.valueOf(2), t.next(LuaValue.ONE).arg(1));
assertEquals(LuaValue.valueOf("two"), t.next(LuaValue.ONE).arg(2));
assertEquals(LuaValue.valueOf("aa"), t.next(LuaValue.valueOf(2)).arg(1));
assertEquals(LuaValue.valueOf("aaa"), t.next(LuaValue.valueOf(2)).arg(2));
assertEquals(LuaValue.valueOf("bb"), t.next(LuaValue.valueOf("aa")).arg(1));
assertEquals(LuaValue.valueOf("bbb"), t.next(LuaValue.valueOf("aa")).arg(2));
assertEquals(LuaValue.NIL, t.next(LuaValue.valueOf("bb")));
}
@Test
void testLoopWithRemoval() {
final LuaTable t = new_Table();
t.set(LuaValue.valueOf(1), LuaValue.valueOf("1"));
t.set(LuaValue.valueOf(3), LuaValue.valueOf("3"));
t.set(LuaValue.valueOf(8), LuaValue.valueOf("4"));
t.set(LuaValue.valueOf(17), LuaValue.valueOf("5"));
t.set(LuaValue.valueOf(26), LuaValue.valueOf("6"));
t.set(LuaValue.valueOf(35), LuaValue.valueOf("7"));
t.set(LuaValue.valueOf(42), LuaValue.valueOf("8"));
t.set(LuaValue.valueOf(60), LuaValue.valueOf("10"));
t.set(LuaValue.valueOf(63), LuaValue.valueOf("11"));
Varargs entry = t.next(LuaValue.NIL);
while ( !entry.isnil(1) ) {
LuaValue k = entry.arg1();
LuaValue v = entry.arg(2);
if ((k.toint() & 1) == 0) {
t.set(k, LuaValue.NIL);
}
entry = t.next(k);
}
int numEntries = 0;
entry = t.next(LuaValue.NIL);
while ( !entry.isnil(1) ) {
LuaValue k = entry.arg1();
// Only odd keys should remain
assertTrue((k.toint() & 1) == 1);
numEntries++;
entry = t.next(k);
}
assertEquals(5, numEntries);
}
@Test
void testLoopWithRemovalAndSet() {
final LuaTable t = new_Table();
t.set(LuaValue.valueOf(1), LuaValue.valueOf("1"));
t.set(LuaValue.valueOf(3), LuaValue.valueOf("3"));
t.set(LuaValue.valueOf(8), LuaValue.valueOf("4"));
t.set(LuaValue.valueOf(17), LuaValue.valueOf("5"));
t.set(LuaValue.valueOf(26), LuaValue.valueOf("6"));
t.set(LuaValue.valueOf(35), LuaValue.valueOf("7"));
t.set(LuaValue.valueOf(42), LuaValue.valueOf("8"));
t.set(LuaValue.valueOf(60), LuaValue.valueOf("10"));
t.set(LuaValue.valueOf(63), LuaValue.valueOf("11"));
Varargs entry = t.next(LuaValue.NIL);
Varargs entry2 = entry;
while ( !entry.isnil(1) ) {
LuaValue k = entry.arg1();
LuaValue v = entry.arg(2);
if ((k.toint() & 1) == 0) {
t.set(k, LuaValue.NIL);
} else {
t.set(k, v.tonumber());
entry2 = t.next(entry2.arg1());
}
entry = t.next(k);
}
int numEntries = 0;
entry = t.next(LuaValue.NIL);
while ( !entry.isnil(1) ) {
LuaValue k = entry.arg1();
// Only odd keys should remain
assertTrue((k.toint() & 1) == 1);
assertTrue(entry.arg(2).type() == LuaValue.TNUMBER);
numEntries++;
entry = t.next(k);
}
assertEquals(5, numEntries);
}
}

View File

@@ -0,0 +1,437 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
import org.junit.jupiter.api.Test;
class TableTest {
protected LuaTable new_Table() {
return new LuaTable();
}
protected LuaTable new_Table(int n, int m) {
return new LuaTable(n, m);
}
private int keyCount(LuaTable t) {
return keys(t).length;
}
private LuaValue[] keys(LuaTable t) {
ArrayList<LuaValue> l = new ArrayList<LuaValue>();
LuaValue k = LuaValue.NIL;
while ( true ) {
Varargs n = t.next(k);
if ((k = n.arg1()).isnil())
break;
l.add(k);
}
return l.toArray(new LuaValue[t.length()]);
}
@Test
void testInOrderIntegerKeyInsertion() {
LuaTable t = new_Table();
for (int i = 1; i <= 32; ++i) {
t.set(i, LuaValue.valueOf("Test Value! " + i));
}
// Ensure all keys are still there.
for (int i = 1; i <= 32; ++i) {
assertEquals("Test Value! " + i, t.get(i).tojstring());
}
// Ensure capacities make sense
assertEquals(0, t.getHashLength());
assertTrue(t.getArrayLength() >= 32);
assertTrue(t.getArrayLength() <= 64);
}
@Test
void testRekeyCount() {
LuaTable t = new_Table();
// NOTE: This order of insertion is important.
t.set(3, LuaInteger.valueOf(3));
t.set(1, LuaInteger.valueOf(1));
t.set(5, LuaInteger.valueOf(5));
t.set(4, LuaInteger.valueOf(4));
t.set(6, LuaInteger.valueOf(6));
t.set(2, LuaInteger.valueOf(2));
for (int i = 1; i < 6; ++i) {
assertEquals(LuaInteger.valueOf(i), t.get(i));
}
assertTrue(t.getArrayLength() >= 3);
assertTrue(t.getArrayLength() <= 12);
assertTrue(t.getHashLength() <= 3);
}
@Test
void testOutOfOrderIntegerKeyInsertion() {
LuaTable t = new_Table();
for (int i = 32; i > 0; --i) {
t.set(i, LuaValue.valueOf("Test Value! " + i));
}
// Ensure all keys are still there.
for (int i = 1; i <= 32; ++i) {
assertEquals("Test Value! " + i, t.get(i).tojstring());
}
// Ensure capacities make sense
assertEquals(32, t.getArrayLength());
assertEquals(0, t.getHashLength());
}
@Test
void testStringAndIntegerKeys() {
LuaTable t = new_Table();
for (int i = 0; i < 10; ++i) {
LuaString str = LuaValue.valueOf(String.valueOf(i));
t.set(i, str);
t.set(str, LuaInteger.valueOf(i));
}
assertTrue(t.getArrayLength() >= 8); // 1, 2, ..., 9
assertTrue(t.getArrayLength() <= 16);
assertTrue(t.getHashLength() >= 11); // 0, "0", "1", ..., "9"
assertTrue(t.getHashLength() <= 33);
LuaValue[] keys = keys(t);
int intKeys = 0;
int stringKeys = 0;
assertEquals(20, keys.length);
for (int i = 0; i < keys.length; ++i) {
LuaValue k = keys[i];
if (k instanceof LuaInteger) {
final int ik = k.toint();
assertTrue(ik >= 0 && ik < 10);
final int mask = 1<<ik;
assertTrue((intKeys & mask) == 0);
intKeys |= mask;
} else if (k instanceof LuaString) {
final int ik = Integer.parseInt(k.strvalue().tojstring());
assertEquals(String.valueOf(ik), k.strvalue().tojstring());
assertTrue(ik >= 0 && ik < 10);
final int mask = 1<<ik;
assertTrue((stringKeys & mask) == 0, "Key \"" + ik + "\" found more than once");
stringKeys |= mask;
} else {
fail("Unexpected type of key found");
}
}
assertEquals(0x03FF, intKeys);
assertEquals(0x03FF, stringKeys);
}
@Test
void testBadInitialCapacity() {
LuaTable t = new_Table(0, 1);
t.set("test", LuaValue.valueOf("foo"));
t.set("explode", LuaValue.valueOf("explode"));
assertEquals(2, keyCount(t));
}
@Test
void testRemove0() {
LuaTable t = new_Table(2, 0);
t.set(1, LuaValue.valueOf("foo"));
t.set(2, LuaValue.valueOf("bah"));
assertNotSame(LuaValue.NIL, t.get(1));
assertNotSame(LuaValue.NIL, t.get(2));
assertEquals(LuaValue.NIL, t.get(3));
t.set(1, LuaValue.NIL);
t.set(2, LuaValue.NIL);
t.set(3, LuaValue.NIL);
assertEquals(LuaValue.NIL, t.get(1));
assertEquals(LuaValue.NIL, t.get(2));
assertEquals(LuaValue.NIL, t.get(3));
}
@Test
void testRemove1() {
LuaTable t = new_Table(0, 1);
t.set("test", LuaValue.valueOf("foo"));
t.set("explode", LuaValue.NIL);
t.set(42, LuaValue.NIL);
t.set(new_Table(), LuaValue.NIL);
t.set("test", LuaValue.NIL);
assertEquals(0, keyCount(t));
t.set(10, LuaInteger.valueOf(5));
t.set(10, LuaValue.NIL);
assertEquals(0, keyCount(t));
}
@Test
void testRemove2() {
LuaTable t = new_Table(0, 1);
t.set("test", LuaValue.valueOf("foo"));
t.set("string", LuaInteger.valueOf(10));
assertEquals(2, keyCount(t));
t.set("string", LuaValue.NIL);
t.set("three", LuaValue.valueOf(3.14));
assertEquals(2, keyCount(t));
t.set("test", LuaValue.NIL);
assertEquals(1, keyCount(t));
t.set(10, LuaInteger.valueOf(5));
assertEquals(2, keyCount(t));
t.set(10, LuaValue.NIL);
assertEquals(1, keyCount(t));
t.set("three", LuaValue.NIL);
assertEquals(0, keyCount(t));
}
@Test
void testShrinkNonPowerOfTwoArray() {
LuaTable t = new_Table(6, 2);
t.set(1, "one");
t.set(2, "two");
t.set(3, "three");
t.set(4, "four");
t.set(5, "five");
t.set(6, "six");
t.set("aa", "aaa");
t.set("bb", "bbb");
t.set(3, LuaValue.NIL);
t.set(4, LuaValue.NIL);
t.set(6, LuaValue.NIL);
t.set("cc", "ccc");
t.set("dd", "ddd");
assertEquals(4, t.getArrayLength());
assertTrue(t.getHashLength() < 10);
assertEquals(5, t.hashEntries);
assertEquals("one", t.get(1).tojstring());
assertEquals("two", t.get(2).tojstring());
assertEquals(LuaValue.NIL, t.get(3));
assertEquals(LuaValue.NIL, t.get(4));
assertEquals("five", t.get(5).tojstring());
assertEquals(LuaValue.NIL, t.get(6));
assertEquals("aaa", t.get("aa").tojstring());
assertEquals("bbb", t.get("bb").tojstring());
assertEquals("ccc", t.get("cc").tojstring());
assertEquals("ddd", t.get("dd").tojstring());
}
@Test
void testInOrderLuaLength() {
LuaTable t = new_Table();
for (int i = 1; i <= 32; ++i) {
t.set(i, LuaValue.valueOf("Test Value! " + i));
assertEquals(i, t.length());
}
}
@Test
void testOutOfOrderLuaLength() {
LuaTable t = new_Table();
for (int j = 8; j < 32; j += 8) {
for (int i = j; i > 0; --i) {
t.set(i, LuaValue.valueOf("Test Value! " + i));
}
assertEquals(j, t.length());
}
}
@Test
void testStringKeysLuaLength() {
LuaTable t = new_Table();
for (int i = 1; i <= 32; ++i) {
t.set("str-" + i, LuaValue.valueOf("String Key Test Value! " + i));
assertEquals(0, t.length());
}
}
@Test
void testMixedKeysLuaLength() {
LuaTable t = new_Table();
for (int i = 1; i <= 32; ++i) {
t.set("str-" + i, LuaValue.valueOf("String Key Test Value! " + i));
t.set(i, LuaValue.valueOf("Int Key Test Value! " + i));
assertEquals(i, t.length());
}
}
private static final void compareLists(LuaTable t, Vector<LuaString> v) {
int n = v.size();
assertEquals(v.size(), t.length());
for (int j = 0; j < n; j++) {
LuaString vj = v.elementAt(j);
String tj = t.get(j+1).tojstring();
assertEquals(vj.tojstring(), tj);
}
}
@Test
void testInsertBeginningOfList() {
LuaTable t = new_Table();
Vector<LuaString> v = new Vector<>();
for (int i = 1; i <= 32; ++i) {
LuaString test = LuaValue.valueOf("Test Value! " + i);
t.insert(1, test);
v.insertElementAt(test, 0);
compareLists(t, v);
}
}
@Test
void testInsertEndOfList() {
LuaTable t = new_Table();
Vector<LuaString> v = new Vector<>();
for (int i = 1; i <= 32; ++i) {
LuaString test = LuaValue.valueOf("Test Value! " + i);
t.insert(0, test);
v.insertElementAt(test, v.size());
compareLists(t, v);
}
}
@Test
void testInsertMiddleOfList() {
LuaTable t = new_Table();
Vector<LuaString> v = new Vector<>();
for (int i = 1; i <= 32; ++i) {
LuaString test = LuaValue.valueOf("Test Value! " + i);
int m = i/2;
t.insert(m+1, test);
v.insertElementAt(test, m);
compareLists(t, v);
}
}
private static final void prefillLists(LuaTable t, Vector<LuaString> v) {
for (int i = 1; i <= 32; ++i) {
LuaString test = LuaValue.valueOf("Test Value! " + i);
t.insert(0, test);
v.insertElementAt(test, v.size());
}
}
@Test
void testRemoveBeginningOfList() {
LuaTable t = new_Table();
Vector<LuaString> v = new Vector<>();
prefillLists(t, v);
for (int i = 1; i <= 32; ++i) {
t.remove(1);
v.removeElementAt(0);
compareLists(t, v);
}
}
@Test
void testRemoveEndOfList() {
LuaTable t = new_Table();
Vector<LuaString> v = new Vector<>();
prefillLists(t, v);
for (int i = 1; i <= 32; ++i) {
t.remove(0);
v.removeElementAt(v.size()-1);
compareLists(t, v);
}
}
@Test
void testRemoveMiddleOfList() {
LuaTable t = new_Table();
Vector<LuaString> v = new Vector<>();
prefillLists(t, v);
for (int i = 1; i <= 32; ++i) {
int m = v.size()/2;
t.remove(m+1);
v.removeElementAt(m);
compareLists(t, v);
}
}
@Test
void testRemoveWhileIterating() {
LuaTable t = LuaValue.tableOf(
new LuaValue[] { LuaValue.valueOf("a"), LuaValue.valueOf("aa"), LuaValue.valueOf("b"),
LuaValue.valueOf("bb"), LuaValue.valueOf("c"), LuaValue.valueOf("cc"), LuaValue.valueOf("d"),
LuaValue.valueOf("dd"), LuaValue.valueOf("e"), LuaValue.valueOf("ee"), },
new LuaValue[] { LuaValue.valueOf("11"), LuaValue.valueOf("22"), LuaValue.valueOf("33"),
LuaValue.valueOf("44"), LuaValue.valueOf("55"), });
// Find expected order after removal.
List<String> expected = new ArrayList<>();
Varargs n;
int i;
for (n = t.next(LuaValue.NIL), i = 0; !n.arg1().isnil(); n = t.next(n.arg1()), ++i) {
if (i%2 == 0)
expected.add(n.arg1() + "=" + n.arg(2));
}
// Remove every other key while iterating over the table.
for (n = t.next(LuaValue.NIL), i = 0; !n.arg1().isnil(); n = t.next(n.arg1()), ++i) {
if (i%2 != 0)
t.set(n.arg1(), LuaValue.NIL);
}
// Iterate over remaining table, and form list of entries still in table.
List<String> actual = new ArrayList<>();
for (n = t.next(LuaValue.NIL); !n.arg1().isnil(); n = t.next(n.arg1())) {
actual.add(n.arg1() + "=" + n.arg(2));
}
assertEquals(expected, actual);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,235 @@
/*******************************************************************************
* Copyright (c) 2012 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.fail;
import org.junit.jupiter.api.Test;
/**
* Tests of basic unary and binary operators on main value types.
*/
class VarargsTest {
static LuaValue A = LuaValue.valueOf("a");
static LuaValue B = LuaValue.valueOf("b");
static LuaValue C = LuaValue.valueOf("c");
static LuaValue D = LuaValue.valueOf("d");
static LuaValue E = LuaValue.valueOf("e");
static LuaValue F = LuaValue.valueOf("f");
static LuaValue G = LuaValue.valueOf("g");
static LuaValue H = LuaValue.valueOf("h");
static LuaValue Z = LuaValue.valueOf("z");
static LuaValue NIL = LuaValue.NIL;
static Varargs A_G = LuaValue.varargsOf(new LuaValue[] { A, B, C, D, E, F, G });
static Varargs B_E = LuaValue.varargsOf(new LuaValue[] { B, C, D, E });
static Varargs C_G = LuaValue.varargsOf(new LuaValue[] { C, D, E, F, G });
static Varargs C_E = LuaValue.varargsOf(new LuaValue[] { C, D, E });
static Varargs DE = LuaValue.varargsOf(new LuaValue[] { D, E });
static Varargs E_G = LuaValue.varargsOf(new LuaValue[] { E, F, G });
static Varargs FG = LuaValue.varargsOf(new LuaValue[] { F, G });
static LuaValue[] Z_H_array = { Z, A, B, C, D, E, F, G, H };
static Varargs A_G_alt = new Varargs.ArrayPartVarargs(Z_H_array, 1, 7);
static Varargs B_E_alt = new Varargs.ArrayPartVarargs(Z_H_array, 2, 4);
static Varargs C_G_alt = new Varargs.ArrayPartVarargs(Z_H_array, 3, 5);
static Varargs C_E_alt = new Varargs.ArrayPartVarargs(Z_H_array, 3, 3);
static Varargs C_E_alt2 = LuaValue.varargsOf(C, D, E);
static Varargs DE_alt = new Varargs.PairVarargs(D, E);
static Varargs DE_alt2 = LuaValue.varargsOf(D, E);
static Varargs E_G_alt = new Varargs.ArrayPartVarargs(Z_H_array, 5, 3);
static Varargs FG_alt = new Varargs.PairVarargs(F, G);
static Varargs NONE = LuaValue.NONE;
private void expectEquals(Varargs x, Varargs y) {
assertEquals(x.narg(), y.narg());
assertEquals(x.arg1(), y.arg1());
assertEquals(x.arg(0), y.arg(0));
assertEquals(x.arg(-1), y.arg(-1));
assertEquals(x.arg(2), y.arg(2));
assertEquals(x.arg(3), y.arg(3));
for (int i = 4; i < x.narg()+2; ++i)
assertEquals(x.arg(i), y.arg(i));
}
@Test
void testSanity() {
expectEquals(A_G, A_G);
expectEquals(A_G_alt, A_G_alt);
expectEquals(A_G, A_G_alt);
expectEquals(B_E, B_E_alt);
expectEquals(C_G, C_G_alt);
expectEquals(C_E, C_E_alt);
expectEquals(C_E, C_E_alt2);
expectEquals(DE, DE_alt);
expectEquals(DE, DE_alt2);
expectEquals(E_G, E_G_alt);
expectEquals(FG, FG_alt);
expectEquals(FG_alt, FG_alt);
expectEquals(A, A);
expectEquals(NONE, NONE);
expectEquals(NIL, NIL);
}
@Test
void testNegativeIndices() {
expectNegSubargsError(A_G);
expectNegSubargsError(A_G_alt);
expectNegSubargsError(B_E);
expectNegSubargsError(B_E_alt);
expectNegSubargsError(C_G);
expectNegSubargsError(C_G_alt);
expectNegSubargsError(C_E);
expectNegSubargsError(C_E_alt);
expectNegSubargsError(C_E_alt2);
expectNegSubargsError(DE);
expectNegSubargsError(DE_alt);
expectNegSubargsError(DE_alt2);
expectNegSubargsError(E_G);
expectNegSubargsError(FG);
expectNegSubargsError(A);
expectNegSubargsError(NONE);
expectNegSubargsError(NIL);
}
private void standardTestsA_G(Varargs a_g) {
expectEquals(A_G, a_g);
expectEquals(A_G, a_g.subargs(1));
expectEquals(C_G, a_g.subargs(3).subargs(1));
expectEquals(E_G, a_g.subargs(5));
expectEquals(E_G, a_g.subargs(5).subargs(1));
expectEquals(FG, a_g.subargs(6));
expectEquals(FG, a_g.subargs(6).subargs(1));
expectEquals(G, a_g.subargs(7));
expectEquals(G, a_g.subargs(7).subargs(1));
expectEquals(NONE, a_g.subargs(8));
expectEquals(NONE, a_g.subargs(8).subargs(1));
standardTestsC_G(A_G.subargs(3));
}
private void standardTestsC_G(Varargs c_g) {
expectEquals(C_G, c_g.subargs(1));
expectEquals(E_G, c_g.subargs(3));
expectEquals(E_G, c_g.subargs(3).subargs(1));
expectEquals(FG, c_g.subargs(4));
expectEquals(FG, c_g.subargs(4).subargs(1));
expectEquals(G, c_g.subargs(5));
expectEquals(G, c_g.subargs(5).subargs(1));
expectEquals(NONE, c_g.subargs(6));
expectEquals(NONE, c_g.subargs(6).subargs(1));
standardTestsE_G(c_g.subargs(3));
}
private void standardTestsE_G(Varargs e_g) {
expectEquals(E_G, e_g.subargs(1));
expectEquals(FG, e_g.subargs(2));
expectEquals(FG, e_g.subargs(2).subargs(1));
expectEquals(G, e_g.subargs(3));
expectEquals(G, e_g.subargs(3).subargs(1));
expectEquals(NONE, e_g.subargs(4));
expectEquals(NONE, e_g.subargs(4).subargs(1));
standardTestsFG(e_g.subargs(2));
}
private void standardTestsFG(Varargs fg) {
expectEquals(FG, fg.subargs(1));
expectEquals(G, fg.subargs(2));
expectEquals(G, fg.subargs(2).subargs(1));
expectEquals(NONE, fg.subargs(3));
expectEquals(NONE, fg.subargs(3).subargs(1));
}
private void standardTestsNone(Varargs none) {
expectEquals(NONE, none.subargs(1));
expectEquals(NONE, none.subargs(2));
}
@Test
void testVarargsSubargs() {
standardTestsA_G(A_G);
standardTestsA_G(A_G_alt);
standardTestsC_G(C_G);
standardTestsC_G(C_G_alt);
standardTestsE_G(E_G);
standardTestsE_G(E_G_alt);
standardTestsFG(FG);
standardTestsFG(FG_alt);
standardTestsNone(NONE);
}
@Test
void testVarargsMore() {
Varargs a_g;
a_g = LuaValue.varargsOf(new LuaValue[] { A, }, LuaValue.varargsOf(new LuaValue[] { B, C, D, E, F, G }));
standardTestsA_G(a_g);
a_g = LuaValue.varargsOf(new LuaValue[] { A, B, }, LuaValue.varargsOf(new LuaValue[] { C, D, E, F, G }));
standardTestsA_G(a_g);
a_g = LuaValue.varargsOf(new LuaValue[] { A, B, C, }, LuaValue.varargsOf(new LuaValue[] { D, E, F, G }));
standardTestsA_G(a_g);
a_g = LuaValue.varargsOf(new LuaValue[] { A, B, C, D, }, LuaValue.varargsOf(E, F, G));
standardTestsA_G(a_g);
a_g = LuaValue.varargsOf(new LuaValue[] { A, B, C, D, E }, LuaValue.varargsOf(F, G));
standardTestsA_G(a_g);
a_g = LuaValue.varargsOf(new LuaValue[] { A, B, C, D, E, F, }, G);
standardTestsA_G(a_g);
}
@Test
void testPairVarargsMore() {
Varargs a_g = new Varargs.PairVarargs(A, new Varargs.PairVarargs(B, new Varargs.PairVarargs(C,
new Varargs.PairVarargs(D, new Varargs.PairVarargs(E, new Varargs.PairVarargs(F, G))))));
standardTestsA_G(a_g);
}
@Test
void testArrayPartMore() {
Varargs a_g;
a_g = new Varargs.ArrayPartVarargs(Z_H_array, 1, 1, new Varargs.ArrayPartVarargs(Z_H_array, 2, 6));
standardTestsA_G(a_g);
a_g = new Varargs.ArrayPartVarargs(Z_H_array, 1, 2, new Varargs.ArrayPartVarargs(Z_H_array, 3, 5));
standardTestsA_G(a_g);
a_g = new Varargs.ArrayPartVarargs(Z_H_array, 1, 3, new Varargs.ArrayPartVarargs(Z_H_array, 4, 4));
standardTestsA_G(a_g);
a_g = new Varargs.ArrayPartVarargs(Z_H_array, 1, 4, new Varargs.ArrayPartVarargs(Z_H_array, 5, 3));
standardTestsA_G(a_g);
a_g = new Varargs.ArrayPartVarargs(Z_H_array, 1, 5, new Varargs.ArrayPartVarargs(Z_H_array, 6, 2));
standardTestsA_G(a_g);
a_g = new Varargs.ArrayPartVarargs(Z_H_array, 1, 6, new Varargs.ArrayPartVarargs(Z_H_array, 7, 1));
standardTestsA_G(a_g);
}
private void expectNegSubargsError(Varargs v) {
String expected_msg = "bad argument #1: start must be > 0";
try {
v.subargs(0);
fail("Failed to throw exception for index 0");
} catch (LuaError e) {
assertEquals(expected_msg, e.getMessage());
}
try {
v.subargs(-1);
fail("Failed to throw exception for index -1");
} catch (LuaError e) {
assertEquals(expected_msg, e.getMessage());
}
}
}

View File

@@ -0,0 +1,262 @@
/*******************************************************************************
* Copyright (c) 2009 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.lang.ref.WeakReference;
import org.junit.jupiter.api.Test;
class WeakTableTest {
@Test
void testWeakValuesTable() {
LuaTable t = WeakTable.make(false, true);
Object obj = new Object();
LuaTable tableValue = new LuaTable();
LuaString stringValue = LuaString.valueOf("this is a test");
LuaTable tableValue2 = new LuaTable();
t.set("table", tableValue);
t.set("userdata", LuaValue.userdataOf(obj, null));
t.set("string", stringValue);
t.set("string2", LuaValue.valueOf("another string"));
t.set(1, tableValue2);
assertTrue(t.getHashLength() >= 4, "table must have at least 4 elements");
// TODO fix assert
// assertTrue(t.getArrayLength() >= 1, "array part must have 1 element");
// check that table can be used to get elements
assertEquals(tableValue, t.get("table"));
assertEquals(stringValue, t.get("string"));
assertEquals(obj, t.get("userdata").checkuserdata());
assertEquals(tableValue2, t.get(1));
// nothing should be collected, since we have strong references here
collectGarbage();
// check that elements are still there
assertEquals(tableValue, t.get("table"));
assertEquals(stringValue, t.get("string"));
assertEquals(obj, t.get("userdata").checkuserdata());
assertEquals(tableValue2, t.get(1));
// drop our strong references
obj = null;
tableValue = null;
tableValue2 = null;
stringValue = null;
// Garbage collection should cause weak entries to be dropped.
collectGarbage();
// check that they are dropped
assertEquals(LuaValue.NIL, t.get("table"));
assertEquals(LuaValue.NIL, t.get("userdata"));
assertEquals(LuaValue.NIL, t.get(1));
assertFalse(t.get("string").isnil(), "strings should not be in weak references");
}
@Test
void testWeakKeysTable() {
LuaTable t = WeakTable.make(true, false);
LuaValue key = LuaValue.userdataOf(new MyData(111));
LuaValue val = LuaValue.userdataOf(new MyData(222));
// set up the table
t.set(key, val);
assertEquals(val, t.get(key));
System.gc();
assertEquals(val, t.get(key));
// drop key and value references, replace them with new ones
WeakReference<LuaValue> origkey = new WeakReference<>(key);
WeakReference<LuaValue> origval = new WeakReference<>(val);
key = LuaValue.userdataOf(new MyData(111));
val = LuaValue.userdataOf(new MyData(222));
// new key and value should be interchangeable (feature of this test class)
assertEquals(key, origkey.get());
assertEquals(val, origval.get());
assertEquals(val, t.get(key));
assertEquals(val, t.get(origkey.get()));
assertEquals(origval.get(), t.get(key));
// value should not be reachable after gc
collectGarbage();
assertEquals(null, origkey.get());
assertEquals(LuaValue.NIL, t.get(key));
collectGarbage();
assertEquals(null, origval.get());
}
@Test
void testNext() {
LuaTable t = WeakTable.make(true, true);
LuaValue key = LuaValue.userdataOf(new MyData(111));
LuaValue val = LuaValue.userdataOf(new MyData(222));
LuaValue key2 = LuaValue.userdataOf(new MyData(333));
LuaValue val2 = LuaValue.userdataOf(new MyData(444));
LuaValue key3 = LuaValue.userdataOf(new MyData(555));
LuaValue val3 = LuaValue.userdataOf(new MyData(666));
// set up the table
t.set(key, val);
t.set(key2, val2);
t.set(key3, val3);
// forget one of the keys
key2 = null;
val2 = null;
collectGarbage();
// table should have 2 entries
int size = 0;
for (LuaValue k = t.next(LuaValue.NIL).arg1(); !k.isnil(); k = t.next(k).arg1()) {
size++;
}
assertEquals(2, size);
}
@Test
void testWeakKeysValuesTable() {
LuaTable t = WeakTable.make(true, true);
LuaValue key = LuaValue.userdataOf(new MyData(111));
LuaValue val = LuaValue.userdataOf(new MyData(222));
LuaValue key2 = LuaValue.userdataOf(new MyData(333));
LuaValue val2 = LuaValue.userdataOf(new MyData(444));
LuaValue key3 = LuaValue.userdataOf(new MyData(555));
LuaValue val3 = LuaValue.userdataOf(new MyData(666));
// set up the table
t.set(key, val);
t.set(key2, val2);
t.set(key3, val3);
assertEquals(val, t.get(key));
assertEquals(val2, t.get(key2));
assertEquals(val3, t.get(key3));
System.gc();
assertEquals(val, t.get(key));
assertEquals(val2, t.get(key2));
assertEquals(val3, t.get(key3));
// drop key and value references, replace them with new ones
WeakReference<LuaValue> origkey = new WeakReference<>(key);
WeakReference<LuaValue> origval = new WeakReference<>(val);
WeakReference<LuaValue> origkey2 = new WeakReference<>(key2);
WeakReference<LuaValue> origval2 = new WeakReference<>(val2);
WeakReference<LuaValue> origkey3 = new WeakReference<>(key3);
WeakReference<LuaValue> origval3 = new WeakReference<>(val3);
key = LuaValue.userdataOf(new MyData(111));
val = LuaValue.userdataOf(new MyData(222));
key2 = LuaValue.userdataOf(new MyData(333));
// don't drop val2, or key3
val3 = LuaValue.userdataOf(new MyData(666));
// no values should be reachable after gc
collectGarbage();
assertEquals(null, origkey.get());
assertEquals(null, origval.get());
assertEquals(null, origkey2.get());
assertEquals(null, origval3.get());
assertEquals(LuaValue.NIL, t.get(key));
assertEquals(LuaValue.NIL, t.get(key2));
assertEquals(LuaValue.NIL, t.get(key3));
// all originals should be gone after gc, then access
val2 = null;
key3 = null;
collectGarbage();
assertEquals(null, origval2.get());
assertEquals(null, origkey3.get());
}
@Test
void testReplace() {
LuaTable t = WeakTable.make(true, true);
LuaValue key = LuaValue.userdataOf(new MyData(111));
LuaValue val = LuaValue.userdataOf(new MyData(222));
LuaValue key2 = LuaValue.userdataOf(new MyData(333));
LuaValue val2 = LuaValue.userdataOf(new MyData(444));
LuaValue key3 = LuaValue.userdataOf(new MyData(555));
LuaValue val3 = LuaValue.userdataOf(new MyData(666));
// set up the table
t.set(key, val);
t.set(key2, val2);
t.set(key3, val3);
LuaValue val4 = LuaValue.userdataOf(new MyData(777));
t.set(key2, val4);
// table should have 3 entries
int size = 0;
for (LuaValue k = t.next(LuaValue.NIL).arg1(); !k.isnil() && size < 1000; k = t.next(k).arg1()) {
size++;
}
assertEquals(3, size);
}
public static class MyData {
public final int value;
public MyData(int value) {
this.value = value;
}
@Override
public int hashCode() {
return value;
}
@Override
public boolean equals(Object o) {
return (o instanceof MyData) && ((MyData) o).value == value;
}
@Override
public String toString() {
return "mydata-" + value;
}
}
static void collectGarbage() {
Runtime rt = Runtime.getRuntime();
rt.gc();
try {
Thread.sleep(20);
rt.gc();
Thread.sleep(20);
} catch (Exception e) {
e.printStackTrace();
}
rt.gc();
}
}