/***************************************************************************
Copyright (C) 2011 Christoph Reichenbach <creichen@gmail.com>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public Licence as
published by the Free Software Foundaton; either version 2 of the
Licence, or (at your option) any later version.
It is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
merchantability or fitness for a particular purpose. See the
GNU General Public Licence for more details.
You should have received a copy of the GNU General Public Licence
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
***************************************************************************/
package edu.umass.pql;
import edu.umass.pql.il.ReductionImpl;
import edu.umass.pql.container.PDefaultMap;
import edu.umass.pql.container.PMap;
import java.util.*;
import org.junit.*;
import java.lang.reflect.Array;
import static org.junit.Assert.*;
public class ReductionTest extends TestBase
{
static java.lang.reflect.Method sumInt = getSumIntMethod();
@Test public void testForallZero() { paratest("para_testForallZero"); }
public void
para_testForallZero()
{
setInts(0, 0, 0, 1);
Reduction red = PQLFactory.Forall(PQLFactory.LT_Int(i0r, i1r),
PQLFactory.LT_Int(i0r, i1r),
i4r, i3r
);
testCount(1, red);
}
@Test public void testForallOne() { paratest("para_testForallOne"); }
public void
para_testForallOne()
{
setInts(0, 0, 0, 1);
Reduction red = PQLFactory.Forall(PQLFactory.LTE_Int(i0r, i1r),
PQLFactory.LTE_Int(i0r, i1r),
i4r, i3r
);
testCount(1, red);
red = PQLFactory.Forall(PQLFactory.LTE_Int(i0r, i1r),
PQLFactory.LT_Int(i0r, i1r),
i4r, i3r
);
testCount(0, red);
}
@Test public void testForallSet() { paratest("para_testForallSet"); }
public void
para_testForallSet()
{
Set<Integer> set = new HashSet<Integer>();
setObjects(set, null, null);
setInts(1, 0, 0);
set.add(2);
set.add(3);
set.add(4);
set.add(17);
ReductionImpl red = (ReductionImpl) PQLFactory.Forall(PQLFactory.CONTAINS(o0r, i1w),
PQLFactory.LT_Int(i0r, i1r),
i4r, i0r
);
testCount(1, red);
set.add(0);
testCount(0, red);
}
@Test
public void
testFusedAPI()
{
final Reduction red = PQLFactory.Reduction(PQLFactory.Reductors.MAP(i0r, l0r, o0w),
PQLFactory.ConjunctiveBlock(), PQLFactory.ConjunctiveBlock());
assertEquals(3, red.getArgsNr());
assertEquals(2, red.getReadArgsNr());
assertEquals(0, red.getOuterReadArgsNr());
red.addReductor(PQLFactory.Reductors.DEFAULT_MAP(d1r, i1r, l1r, o1w));
assertEquals(7, red.getArgsNr());
assertEquals(5, red.getReadArgsNr());
assertEquals(1, red.getOuterReadArgsNr());
red.addReductor(PQLFactory.Reductors.DEFAULT_MAP(d2r, i2r, l2r, o2w));
assertEquals(11, red.getArgsNr());
assertEquals(8, red.getReadArgsNr());
assertEquals(2, red.getOuterReadArgsNr());
int[] expected_args = new int[] {
d1r, d2r, i0r, l0r, i1r, l1r, i2r, l2r, o0w, o1w, o2w
};
assertEquals(11, expected_args.length);
for (int k = -1; k < expected_args.length; k++) {
if (k >= 0) {
expected_args[k] = Env.encodeVar(TYPE_INT, k+10);
red.setArg(k, expected_args[k]);
}
for (int i = 0; i < expected_args.length; i++)
assertEquals("argument #" + i + ": " + Env.showVar(expected_args[i]) + " vs " + Env.showVar(red.getArg(i)) + " at k=" + k,
expected_args[i],
red.getArg(i));
}
}
@Test
public void
testPredicateIteration()
{
setInts(0, 1, 0);
testCount(1, PQLFactory.LT_Int(i0r, i1r));
}
Set<Integer> setLow = new HashSet<Integer>();
Set<Integer> setLow2 = new HashSet<Integer>();
Set<Integer> setHigh = new HashSet<Integer>();
protected void
resetSets()
{
this.reset();
}
@Override
protected void
reset()
{
setObjects(setLow, setHigh, setLow2);
setLow.clear();
setLow2.clear();
setHigh.clear();
setLow.add(2);
setLow.add(3);
setLow.add(5);
setLow.add(7);
setLow2.add(20);
setLow2.add(30);
setLow2.add(50);
setLow2.add(7);
setHigh.add(20);
setHigh.add(300);
setHigh.add(5000);
setHigh.add(70000);
}
@Test
public void
testComboBlock()
{
resetSets();
ControlStructure b = PQLFactory.ConjunctiveBlock(new Join[] {
PQLFactory.CONTAINS(o0r, i0w),
PQLFactory.CONTAINS(o1r, i1w)
});
testCount(16, b);
}
@Test public void testMergedForall() { paratest("para_testMergedForall"); }
public void
para_testMergedForall()
{
resetSets();
ControlStructure b = PQLFactory.ConjunctiveBlock(new Join[] {
PQLFactory.CONTAINS(o0r, i0w),
PQLFactory.CONTAINS(o1r, i1w)
});
setInts(0, 0, 0, 1);
testCount(1, PQLFactory.Forall(b,
PQLFactory.LT_Int(i0r, i1r),
i4r, i3r
));
}
@Test public void testNestedForall() { paratest("para_testNestedForall"); }
public void
para_testNestedForall()
{
resetSets();
setInts(0, 0, 0, 1);
ControlStructure b = PQLFactory.ConjunctiveBlock(new Join[] {
PQLFactory.Forall(PQLFactory.CONTAINS(o0r, i0w),
PQLFactory.LT_Int(i0r, i1r),
i4r, i3r)
});
testCount(1, PQLFactory.Forall(PQLFactory.CONTAINS(o1r, i1w),
b,
i4r, i3r));
}
@Test public void testExistsZero() { paratest("para_testExistsZero"); }
public void
para_testExistsZero()
{
setInts(0, 0, 0, 1);
Reduction red = PQLFactory.Exists(PQLFactory.LT_Int(i0r, i1r),
PQLFactory.LT_Int(i0r, i1r),
i4r, i3r);
testCount(0, red);
}
@Test public void testExistsOne() { paratest("para_testExistsOne"); }
public void
para_testExistsOne()
{
setInts(0, 0, 0, 1);
Reduction red = PQLFactory.Exists(PQLFactory.LTE_Int(i0r, i1r),
PQLFactory.LTE_Int(i0r, i1r),
i4r, i3r);
testCount(1, red);
red = PQLFactory.Exists(PQLFactory.LTE_Int(i0r, i1r),
PQLFactory.LT_Int(i0r, i1r),
i4r, i3r);
testCount(0, red);
}
@Test public void testExistsSet() { paratest("para_testExistsSet"); }
public void
para_testExistsSet()
{
Set<Integer> set = new HashSet<Integer>();
setObjects(set, null, null);
setInts(15, 0, 0, 1);
set.add(2);
set.add(3);
set.add(4);
set.add(15);
Reduction red = PQLFactory.Exists(PQLFactory.CONTAINS(o0r, i1w),
PQLFactory.LT_Int(i0r, i1r),
i4r, i3r);
testCount(0, red);
set.add(17);
testCount(1, red);
}
@Test public void testNestedExists() { paratest("para_testNestedExists"); }
public void
para_testNestedExists()
{
resetSets();
setInts(0, 0, 0, 1);
ControlStructure b = PQLFactory.ConjunctiveBlock(new Join[] {
PQLFactory.Exists(PQLFactory.CONTAINS(o0r, i0w),
PQLFactory.EQ_Int(i0r, i1r),
i5r, i3r)
});
testCount(1, PQLFactory.Exists(PQLFactory.CONTAINS(o2r, i1w),
b,
i6r, i3r
));
}
@Test public void testNestedNotExists() { paratest("para_testNestedNotExists"); }
public void
para_testNestedNotExists()
{
resetSets();
setInts(0, 0, 0, 1);
ControlStructure b = PQLFactory.ConjunctiveBlock(new Join[] {
PQLFactory.Exists(PQLFactory.CONTAINS(o0r, i0w),
PQLFactory.EQ_Int(i0r, i1r),
i4r, i3r)
});
testCount(0, PQLFactory.Exists(PQLFactory.CONTAINS(o1r, i1w),
b,
i5r, i3r
));
}
public static java.lang.reflect.Method
getSumIntMethod()
{
try {
return Query.class.getDeclaredMethod("sumInt", int.class, int.class);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Test
public void
testSumInt()
{
testReductor(PQLFactory.Reductors.METHOD_ADAPTER(sumInt, i1w, i0w),
new Object[] { 1, 1, 1, 1, 1, 1, 1, 2, 2 },
null,
new Object[] { 11 },
true);
}
@Test
public void
testSumLong() throws NoSuchMethodException
{
testReductor(PQLFactory.Reductors.METHOD_ADAPTER(Query.class.getDeclaredMethod("sumLong", long.class, long.class), i1w, i0w),
new Object[] { 1, 1, 1, 1, 1, 1, 1, 2, 2, 1000000000000l },
null,
new Object[] { (1000000000000l + 11l) },
true);
}
@Test
public void
testSumDouble() throws NoSuchMethodException
{
testReductor(PQLFactory.Reductors.METHOD_ADAPTER(Query.class.getDeclaredMethod("sumDouble", double.class, double.class), i1w, i0w),
new Object[] { 1, 1, 1, 1, 1, 1, 1, 1.75, 2 },
null,
new Object[] { 10.75 },
true);
}
public static Set<Integer>
setUnion(Set<Integer> s1, Set<Integer> s2)
{
if (s1 == null)
return s2;
if (s2 == null)
return s1;
final HashSet<Integer> retval = new HashSet<Integer>(s1);
retval.addAll(s2);
return retval;
}
@Test
public void
testSetUnion() throws NoSuchMethodException
{
final HashSet<Integer> s0 = new HashSet<Integer>();
final HashSet<Integer> s1 = new HashSet<Integer>();
final HashSet<Integer> s2 = new HashSet<Integer>();
final HashSet<Integer> s3 = new HashSet<Integer>();
final HashSet<Integer> s4 = new HashSet<Integer>();
final HashSet<Integer> s_all = new HashSet<Integer>();
s0.add(0);
s1.add(1);
s2.add(2);
s3.add(17);
s4.add(2);
s_all.add(0);
s_all.add(1);
s_all.add(2);
s_all.add(17);
testReductor(PQLFactory.Reductors.METHOD_ADAPTER(ReductionTest.class.getDeclaredMethod("setUnion", Set.class, Set.class), i1w, i0w),
new Object[] { s0, s1, s2, s3, s4 },
null,
new Object[] { s_all },
true);
}
@Test
public void
testSet()
{
Set<Integer> resultset = new HashSet<Integer>();
resultset.add(1);
resultset.add(3);
resultset.add(7);
resultset.add(15);
testReductor(PQLFactory.Reductors.SET(i1w, o0w),
new Object[] { 1, 3, 7, 3, 1, 15 },
null,
new Object[] { resultset },
true);
}
@Test
public void
testMapSuccess()
{
Map<Integer, String> resultmap = new PMap<Integer, String>();
resultmap.put(1, "one");
resultmap.put(7, "seven");
resultmap.put(42, "fourty-two");
testReductor(PQLFactory.Reductors.MAP(i1r, i2r, o0w),
new Object[] { 1, "one",
42, "fourty-two",
7, "seven",
42, "fourty-two", },
null,
new Object[] { resultmap },
true);
}
@Test
public void
testMapDefault()
{
PDefaultMap<Integer, String> resultmap = new PDefaultMap<Integer, String>("twenty-three");
resultmap.put(1, "one");
resultmap.put(7, "seven");
resultmap.put(42, "fourty-two");
setInts(0, 0, 0, 23);
testReductor(PQLFactory.Reductors.DEFAULT_MAP(i3r, i1r, i2r, o0w),
new Object[] { "twenty-three" },
new Object[] { 1, "one",
42, "fourty-two",
7, "seven",
42, "fourty-two", },
null,
new Object[] { resultmap },
true);
}
@Test
public void
testMapFailure()
{
Map<Integer, String> resultmap = new PMap<Integer, String>();
resultmap.put(3, "three");
resultmap.put(7, "seven");
resultmap.put(42, "fourty-two");
testReductor(PQLFactory.Reductors.MAP(i1r, i2r, o0w),
new Object[] { 3, "three",
42, "fourty-two",
7, "seven",
42, "fourty-two",
3, "five" },
null,
new Object[] { new AmbiguousMapKeyException(new Integer(3)) },
true);
}
// --------------------------------------------------------------------------------
// int[] expected_int_array = new int[5];
// {
// expected_int_array[1] = -1;
// expected_int_array[3] = -3;
// expected_int_array[4] = -4;
// }
// @Test
// public void
// testIntArraySuccess()
// {
// testReductor(PQLFactory.Reductors.INT_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -1,
// 4, -4,
// 3, -3,
// 4, -4 },
// null,
// new Object[] { expected_int_array },
// true);
// }
// @Test
// public void
// testIntArrayFailure()
// {
// testReductor(PQLFactory.Reductors.INT_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -1,
// 4, -4,
// 3, -3,
// 4, -4,
// 3, 5},
// null,
// new Object[] { new AmbiguousMapKeyException(new Integer(3)) },
// true);
// }
// @Test
// public void
// testIntArraySizeFailure()
// {
// testReductor(PQLFactory.Reductors.INT_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -1,
// 4, -4,
// 3, -3,
// -17, 17,
// 4, -4 },
// null,
// new Object[] { new ArrayIndexOutOfBoundsException(-17) },
// true);
// }
// // --------------------------------------------------------------------------------
// boolean[] expected_bool_array = new boolean[5];
// {
// expected_bool_array[1] = true;
// expected_bool_array[3] = true;
// expected_bool_array[4] = false;
// }
// @Test
// public void
// testBooleanArraySuccess()
// {
// testReductor(PQLFactory.Reductors.BOOLEAN_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, true,
// 4, false,
// 3, true,
// 4, false },
// null,
// new Object[] { expected_bool_array },
// true);
// }
// @Test
// public void
// testBooleanArrayFailure()
// {
// testReductor(PQLFactory.Reductors.BOOLEAN_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, true,
// 4, false,
// 3, true,
// 4, false,
// 3, false},
// null,
// new Object[] { new AmbiguousMapKeyException(new Integer(3)) },
// true);
// }
// @Test
// public void
// testBooleanArraySizeFailure()
// {
// testReductor(PQLFactory.Reductors.BOOLEAN_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, true,
// 4, true,
// 3, true,
// -17, true,
// 4, true },
// null,
// new Object[] { new ArrayIndexOutOfBoundsException(-17) },
// true);
// }
// // --------------------------------------------------------------------------------
// byte[] expected_byte_array = new byte[5];
// {
// expected_byte_array[1] = -1;
// expected_byte_array[3] = -3;
// expected_byte_array[4] = -4;
// }
// @Test
// public void
// testByteArraySuccess()
// {
// testReductor(PQLFactory.Reductors.BYTE_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -1,
// 4, -4,
// 3, -3,
// 4, -4 },
// null,
// new Object[] { expected_byte_array },
// true);
// }
// @Test
// public void
// testByteArrayFailure()
// {
// testReductor(PQLFactory.Reductors.BYTE_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -1,
// 4, -4,
// 3, -3,
// 4, -4,
// 3, 5},
// null,
// new Object[] { new AmbiguousMapKeyException(new Integer(3)) },
// true);
// }
// @Test
// public void
// testByteArraySizeFailure()
// {
// testReductor(PQLFactory.Reductors.BYTE_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -1,
// 4, -4,
// 3, -3,
// -17, 17,
// 4, -4 },
// null,
// new Object[] { new ArrayIndexOutOfBoundsException(-17) },
// true);
// }
// // --------------------------------------------------------------------------------
// short[] expected_short_array = new short[5];
// {
// expected_short_array[1] = -1;
// expected_short_array[3] = -3;
// expected_short_array[4] = -4;
// }
// @Test
// public void
// testShortArraySuccess()
// {
// testReductor(PQLFactory.Reductors.SHORT_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -1,
// 4, -4,
// 3, -3,
// 4, -4 },
// null,
// new Object[] { expected_short_array },
// true);
// }
// @Test
// public void
// testShortArrayFailure()
// {
// testReductor(PQLFactory.Reductors.SHORT_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -1,
// 4, -4,
// 3, -3,
// 4, -4,
// 3, 5},
// null,
// new Object[] { new AmbiguousMapKeyException(new Integer(3)) },
// true);
// }
// @Test
// public void
// testShortArraySizeFailure()
// {
// testReductor(PQLFactory.Reductors.SHORT_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -1,
// 4, -4,
// 3, -3,
// -17, 17,
// 4, -4 },
// null,
// new Object[] { new ArrayIndexOutOfBoundsException(-17) },
// true);
// }
// // --------------------------------------------------------------------------------
// char[] expected_char_array = new char[5];
// {
// expected_char_array[1] = 'a';
// expected_char_array[3] = 'b';
// expected_char_array[4] = 'c';
// }
// @Test
// public void
// testCharArraySuccess()
// {
// testReductor(PQLFactory.Reductors.CHAR_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, 'a',
// 4, 'c',
// 3, 'b',
// 4, 'c' },
// null,
// new Object[] { expected_char_array },
// true);
// }
// @Test
// public void
// testCharArrayFailure()
// {
// testReductor(PQLFactory.Reductors.CHAR_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, 'a',
// 4, 'c',
// 3, 'b',
// 4, 'c',
// 3, 'x'},
// null,
// new Object[] { new AmbiguousMapKeyException(new Integer(3)) },
// true);
// }
// @Test
// public void
// testCharArraySizeFailure()
// {
// testReductor(PQLFactory.Reductors.CHAR_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, 'a',
// 4, 'b',
// 3, 'c',
// -17, 'd',
// 4, 'b' },
// null,
// new Object[] { new ArrayIndexOutOfBoundsException(-17) },
// true);
// }
// // --------------------------------------------------------------------------------
// long[] expected_long_array = new long[5];
// {
// expected_long_array[1] = -10000000000l;
// expected_long_array[3] = -30000000000l;
// expected_long_array[4] = -40000000000l;
// }
// @Test
// public void
// testLongArraySuccess()
// {
// testReductor(PQLFactory.Reductors.LONG_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -10000000000l,
// 4, -40000000000l,
// 3, -30000000000l,
// 4, -40000000000l },
// null,
// new Object[] { expected_long_array },
// true);
// }
// @Test
// public void
// testLongArrayFailure()
// {
// testReductor(PQLFactory.Reductors.LONG_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -10000000000l,
// 4, -40000000000l,
// 3, -30000000000l,
// 4, -40000000000l,
// 3, 5l},
// null,
// new Object[] { new AmbiguousMapKeyException(new Integer(3)) },
// true);
// }
// @Test
// public void
// testLongArraySizeFailure()
// {
// testReductor(PQLFactory.Reductors.LONG_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -10000000000l,
// 4, -40000000000l,
// 3, -30000000000l,
// -17, 170000000000l,
// 4, -40000000000l },
// null,
// new Object[] { new ArrayIndexOutOfBoundsException(-17) },
// true);
// }
// // --------------------------------------------------------------------------------
// double[] expected_double_array = new double[5];
// {
// expected_double_array[1] = -1.5;
// expected_double_array[3] = -3.5;
// expected_double_array[4] = -4.5;
// }
// @Test
// public void
// testDoubleArraySuccess()
// {
// testReductor(PQLFactory.Reductors.DOUBLE_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -1.5,
// 4, -4.5,
// 3, -3.5,
// 4, -4.5 },
// null,
// new Object[] { expected_double_array },
// true);
// }
// @Test
// public void
// testDoubleArrayFailure()
// {
// testReductor(PQLFactory.Reductors.DOUBLE_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -1.5,
// 4, -4.5,
// 3, -3.5,
// 4, -4.5,
// 3, 5.5},
// null,
// new Object[] { new AmbiguousMapKeyException(new Integer(3)) },
// true);
// }
// @Test
// public void
// testDoubleArraySizeFailure()
// {
// testReductor(PQLFactory.Reductors.DOUBLE_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -1.5,
// 4, -4.5,
// 3, -3.5,
// -17, 17.5,
// 4, -4.5 },
// null,
// new Object[] { new ArrayIndexOutOfBoundsException(-17) },
// true);
// }
// // --------------------------------------------------------------------------------
// float[] expected_float_array = new float[5];
// {
// expected_float_array[1] = -1.5f;
// expected_float_array[3] = -3.5f;
// expected_float_array[4] = -4.5f;
// }
// @Test
// public void
// testFloatArraySuccess()
// {
// testReductor(PQLFactory.Reductors.FLOAT_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -1.5f,
// 4, -4.5f,
// 3, -3.5f,
// 4, -4.5f },
// null,
// new Object[] { expected_float_array },
// true);
// }
// @Test
// public void
// testFloatArrayFailure()
// {
// testReductor(PQLFactory.Reductors.FLOAT_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -1.5f,
// 4, -4.5f,
// 3, -3.5f,
// 4, -4.5f,
// 3, 5.5f},
// null,
// new Object[] { new AmbiguousMapKeyException(new Integer(3)) },
// true);
// }
// @Test
// public void
// testFloatArraySizeFailure()
// {
// testReductor(PQLFactory.Reductors.FLOAT_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, -1.5f,
// 4, -4.5f,
// 3, -3.5f,
// -17, 17.5f,
// 4, -4.5f },
// null,
// new Object[] { new ArrayIndexOutOfBoundsException(-17) },
// true);
// }
// // --------------------------------------------------------------------------------
// final Object obj1 = new Integer(42);
// final Object obj3 = new String("foo");
// final Object obj4 = new int[2];
// Object[] expected_object_array = new Object[5];
// {
// expected_object_array[1] = obj1;
// expected_object_array[3] = obj3;
// expected_object_array[4] = obj4;
// }
// @Test
// public void
// testObjectArraySuccess()
// {
// testReductor(PQLFactory.Reductors.OBJECT_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, obj1,
// 4, obj4,
// 3, obj3,
// 4, obj4 },
// null,
// new Object[] { expected_object_array },
// true);
// }
// @Test
// public void
// testObjectArrayFailure()
// {
// testReductor(PQLFactory.Reductors.OBJECT_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, obj1,
// 4, obj4,
// 3, obj3,
// 4, new Integer(2),
// 3, obj3},
// null,
// new Object[] { new AmbiguousMapKeyException(new Integer(4)) },
// true);
// }
// @Test
// public void
// testObjectArraySizeFailure()
// {
// testReductor(PQLFactory.Reductors.OBJECT_ARRAY(i1r, i2r, o0w),
// new Object[] { 1, obj1,
// 4, obj4,
// 3, obj3,
// -17, obj1,
// 4, obj4 },
// null,
// new Object[] { new ArrayIndexOutOfBoundsException(-17) },
// true);
// }
// --------------------------------------------------------------------------------
// @Test
// public void
// testReductionAPI()
// {
// Reductor reductor1 = PQLFactory.Reductors.DOUBLE_ARRAY(i1r, i2r, o0w);
// Reduction red = PQLFactory.Reduction(reductor1,
// PQLFactory.LT_Int(i0r, i1r),
// PQLFactory.LT_Int(i0r, i1r)
// );
// checkAPI(red,
// 2, 3, new int[] { i1r, i2r, o0w });
// }
@Test
public void
testForallManifestTrue()
{
testReductor(PQLFactory.Reductors.FORALL(i1w, i0w),
new Object[] { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
null,
new Object[] { 1 },
true);
}
@Test
public void
testForallManifestFalse0()
{
testReductor(PQLFactory.Reductors.FORALL(i1w, i0w),
new Object[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 },
null,
new Object[] { 0 },
true);
}
@Test
public void
testForallManifestFalse1()
{
testReductor(PQLFactory.Reductors.FORALL(i1w, i0w),
new Object[] { 1, 1, 1, 1, 0, 1, 1, 1, 1, 1 },
null,
new Object[] { 0 },
true);
}
@Test
public void
testForallManifestFalse2()
{
testReductor(PQLFactory.Reductors.FORALL(i1w, i0w),
new Object[] { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
null,
new Object[] { 0 },
true);
}
@Test
public void
testExistsManifestFalse()
{
testReductor(PQLFactory.Reductors.EXISTS(i1w, i0w),
new Object[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
null,
new Object[] { 0 },
true);
}
@Test
public void
testExistsManifestTrue0()
{
testReductor(PQLFactory.Reductors.EXISTS(i1w, i0w),
new Object[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
null,
new Object[] { 1 },
true);
}
@Test
public void
testExistsManifestTrue1()
{
testReductor(PQLFactory.Reductors.EXISTS(i1w, i0w),
new Object[] { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
null,
new Object[] { 1 },
true);
}
@Test
public void
testExistsManifestTrue2()
{
testReductor(PQLFactory.Reductors.EXISTS(i1w, i0w),
new Object[] { 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
null,
new Object[] { 1 },
true);
}
// --------------------------------------------------------------------------------
// Fused
@Test
public void
testFusedReductionAPI()
{
Reductor reductor1 = PQLFactory.Reductors.MAP(i0r, l0r, o0w);
Reductor reductor2 = PQLFactory.Reductors.MAP(i1r, l1r, o1w);
Reductor reductor3 = PQLFactory.Reductors.MAP(i2r, l2r, o2w);
Reduction red = PQLFactory.Reduction(reductor1,
PQLFactory.LT_Int(i0r, i1r),
PQLFactory.LT_Int(i0r, i1r)
);
checkAPI(red,
2, 3, new int[] { i0r, l0r, o0w });
red.addReductor(reductor2);
checkAPI(red,
4, 6, new int[] { i0r, l0r, i1r, l1r, o0w, o1w });
red.addReductor(reductor3);
checkAPI(red,
6, 9, new int[] { i0r, l0r, i1r, l1r, i2r, l2r, o0w, o1w, o2w });
}
@Test public void testFusedSetMap() { paratest("para_testFusedSetMap"); }
public void
para_testFusedSetMap() // compute set and array at same time
{
int[] int_array = new int[] { 3, 5, 7, 9 };
Map<Integer, Integer> int_map = new PMap<Integer, Integer>();
for (int k = 0; k < int_array.length; k++)
int_map.put(k, int_array[k]);
Set<Integer> set = new HashSet<Integer>();
set.add(2);
set.add(4);
set.add(6);
set.add(8);
setLongs(0l, 3l, 0l);
setInts(2, 1, 0);
Join generator = PQLFactory.INT_RANGE_CONTAINS(l0r, l1r, i5w);
ControlStructure computer = PQLFactory.ConjunctiveBlock(new Join[] {
PQLFactory.MUL_Int(i5r, i0r, i2w),
PQLFactory.ADD_Int(i2r, i0r, i3w),
PQLFactory.ADD_Int(i3r, i1r, i4w),
});
Reductor r1 = PQLFactory.Reductors.MAP(i5r, i4r, o0w);
Reductor r2 = PQLFactory.Reductors.SET(i3r, o1w);
Reduction red = PQLFactory.Reduction(r1,
generator,
computer);
red.addReductor(r2);
testCount(1, red);
check_equal(int_map, env.getObject(o0r));
check_equal(set, env.getObject(o1r));
}
@Test public void testFusedTruthMap() { paratest("para_testFusedTruthMap"); }
public void
para_testFusedTruthMap() // compute map and truth value at same time
{
Map<Long, Integer> map = new PMap<Long, Integer>();
map.put(0l, 1);
map.put(1l, 2);
map.put(2l, 3);
map.put(3l, 4);
setLongs(0l, 3l, 0l);
setInts(0, 1, 0);
Join generator = PQLFactory.INT_RANGE_CONTAINS(l0r, l1r, l2w);
ControlStructure computer = PQLFactory.ConjunctiveBlock(new Join[] {
PQLFactory.ADD_Int(l2r, i1r, i4w),
PQLFactory.Bool(PQLFactory.LT_Int(i0r, i4r),
i2w)
});
Reductor r1 = PQLFactory.Reductors.FORALL(i2r, i3w);
Reductor r2 = PQLFactory.Reductors.MAP(l2r, i4r, o0w);
Reduction red = PQLFactory.Reduction(r1,
generator,
computer);
red.addReductor(r2);
testCount(1, red);
check_equal(map, env.getObject(o0r));
check_equal(1, env.getInt(i3r));
}
public void
testFusedTruthCheck(int index_base, int contents_base,
int expected_lhs, int expected_rhs)
{
int[] source = new int[] { 1, 2, 3, 4, 5 };
setObjects(source, null, null);
setLongs(index_base, contents_base, 0l);
Join generator = PQLFactory.ARRAY_LOOKUP_Int(o0r, i0w, i1w);
ControlStructure computer = PQLFactory.ConjunctiveBlock(new Join[] {
PQLFactory.Bool(PQLFactory.LT_Int(l0r, i0r),
i2w),
PQLFactory.Bool(PQLFactory.LT_Int(l1r, i1r),
i3w)
});
Reductor r1 = PQLFactory.Reductors.FORALL(i2r, i4w);
Reductor r2 = PQLFactory.Reductors.FORALL(i3r, i5w);
Reduction red = PQLFactory.Reduction(r1,
generator,
computer);
red.addReductor(r2);
testCount(1, red);
check_equal(expected_lhs, env.getInt(i4r));
check_equal(expected_rhs, env.getInt(i5r));
}
@Test public void testFusedTruthTruthSuccess() { paratest("para_testFusedTruthTruthSuccess"); }
public void
para_testFusedTruthTruthSuccess() // compute two truth values at same time, left failing
{
testFusedTruthCheck(-1, 0,
1, // all indices will be > -1
1);// all contents will be > 0
}
@Test public void testFusedTruthTruthLFail() { paratest("para_testFusedTruthTruthLFail"); }
public void
para_testFusedTruthTruthLFail() // compute two truth values at same time, left failing
{
testFusedTruthCheck(0, 0,
0, // one index will be zero, i.e., not > 0
1);// all contents will be > 0
}
@Test public void testFusedTruthTruthRFail() { paratest("para_testFusedTruthTruthRFail"); }
public void
para_testFusedTruthTruthRFail() // compute two truth values at same time, left failing
{
testFusedTruthCheck(-1, 1,
1,
0);
}
@Test public void testFusedTruthTruthLRFail() { paratest("para_testFusedTruthTruthLRFail"); }
public void
para_testFusedTruthTruthLRFail() // compute two truth values at same time, left failing
{
testFusedTruthCheck(0, 1,
0,
0);
}
// --------------------------------------------------------------------------------
public void
testReductor(Reductor reductor,
Object[] values,
boolean[] successes,
Object[] expected,
boolean expected_success)
{
testReductor(reductor, null, values, successes, expected, expected_success);
}
public void
testReductor(Reductor reductor,
Object[] outer_values,
Object[] values,
boolean[] successes,
Object[] expected,
boolean expected_success)
{
if (reductor.getInnerReductor() == null
&& !reductor.isMethodAdapter())
checkFactory(reductor, PQLFactory.Gen.REDUCTOR_FACTORY_CLASS, reductor.getName());
(new ReductorTest(reductor, outer_values, values, successes, expected, expected_success)).test();
}
public static void
check_equal(Object lhs, Object rhs)
{
if (lhs == null) {
assertNull(rhs);
return;
} else if (rhs == null)
fail();
assertEquals(lhs.getClass().isArray(),
rhs.getClass().isArray());
if (lhs.getClass().isArray()) {
assertEquals(Array.getLength(lhs),
Array.getLength(rhs));
for (int j = 0; j < Array.getLength(lhs); j++)
check_equal(Array.get(lhs, j),
Array.get(rhs, j));
} else {
// if (lhs instanceof Set
// && rhs instanceof Set) {
// Set l = (Set) lhs;
// Set r = (Set) rhs;
// assertTrue(l.containsAll(r));
// assertTrue(r.containsAll(l));
// } else if (lhs instanceof Map
// && rhs instanceof Map) {
// Map l = (Map) lhs;
// Map r = (Map) rhs;
// Set l_keys = l.keySet();
// Set r_keys = r.keySet();
// assertTrue(l_keys.containsAll(r_keys));
// assertTrue(r_keys.containsAll(l_keys));
// for (Object k : l_keys)
// assertEquals(l.get(k),
// r.get(k));
// } else
assertEquals(lhs, rhs);
}
}
private class ReductorTest
{
Reductor reductor;
Object[] outer_inputs;
Object[] inputs;
boolean[] successes;
Object[] expected;
boolean expected_success;
int read_delta; // number of input entries to set up for each reductor test
int read_offset_start; // start offset of the first input entry (same as getOuterReadArgsNr())
public ReductorTest(Reductor reductor,
Object[] outer_values,
Object[] values,
boolean[] successes,
Object[] expected,
boolean expected_success)
{
this.outer_inputs = outer_values;
this.inputs = values;
this.reductor = reductor;
this.successes = successes;
this.expected_success = expected_success;
this.expected = expected;
this.read_delta = reductor.getInnerReadArgsNr();
this.read_offset_start = reductor.getOuterReadArgsNr();
}
public void
test()
{
assertTrue(reductor.getArgsNr() >= 0);
assertTrue(reductor.getInnerReadArgsNr() >= 0);
assertTrue(reductor.getOuterReadArgsNr() >= 0);
assertTrue(reductor.getOuterReadArgsNr() <= reductor.getReadArgsNr());
assertTrue(reductor.getReadArgsNr() <= reductor.getReadArgsNr());
assertEquals(reductor.getOuterReadArgsNr(), this.outer_inputs == null ? 0 : this.outer_inputs.length);
if (this.successes == null
&& this.inputs == null)
throw new RuntimeException("Forgot to specify expected results");
for (int i = 0; i < reductor.getArgsNr(); i++) {
reductor.setArg(i, i0r);
assertEquals(i0r, reductor.getArg(i));
reductor.setArg(i, o1w);
assertEquals(o1w, reductor.getArg(i));
}
int max_size;
if (successes != null)
max_size = successes.length + 2;
else
max_size = inputs.length + 1;
for (int i = 0; i < reductor.getOuterReadArgsNr(); i++) {
final int register = Env.encodeReadVar(VarConstants.TYPE_OBJECT, i);
reductor.setArg(i, register);
env.setObject(register, this.outer_inputs[i]);
}
for (int i = 1; i < max_size; i++) {
// System.err.println("alpha:" + i);
try {
this.testReductorCountSliced(i);
} catch (Exception emk) {
check_exn_result(emk);
}
// System.err.println("bravo:" + i);
try {
this.testReductorCountChunked(i);
} catch (Exception emk) {
check_exn_result(emk);
}
}
}
private void
check_exn_result(Exception e)
{
assertEquals(1, this.expected.length);
if (this.expected[0] instanceof ArrayIndexOutOfBoundsException)
assertTrue(e instanceof ArrayIndexOutOfBoundsException); // unfortunately we can't rely on the exact message
else {
try {
assertEquals(this.expected[0], e);
} catch (Throwable t) {
if (t instanceof Exception) {
System.err.println("\nUnexpected exception:");
t.printStackTrace();
}
throw new RuntimeException(t);
}
}
}
private void
check_result(Reductor reductor, boolean succeeded)
{
final int first_write_var = reductor.getReadArgsNr();
assertEquals(expected_success, succeeded);
if (expected != null) {
for (int i = 0; i < expected.length; i++) {
Object actual_result =
env.getObject(Env.encodeReadVar(VarConstants.TYPE_OBJECT,
i + first_write_var));
check_equal(expected[i], actual_result);
}
}
}
public void
testReductorCountSliced(int reductors_nr)
{
final Reductor main_reductor = reductor;
boolean success = true;
main_reductor.setup(env);
// set up input variables
for (int i = reductor.getOuterReadArgsNr(); i < reductor.getReadArgsNr(); i++)
reductor.setArg(i, Env.encodeReadVar(VarConstants.TYPE_OBJECT, i));
for (int i = reductor.getReadArgsNr(); i < reductor.getArgsNr(); i++)
reductor.setArg(i, Env.encodeWriteVar(VarConstants.TYPE_OBJECT, i));
for (int reductor_index = 0; reductor_index < reductors_nr; reductor_index++) {
final Reductor clone_reductor = reductor.copy();
clone_reductor.setup(env);
int inputs_index = this.read_delta * reductor_index;
int success_index = reductor_index;
// For each feasible value
while (((this.inputs == null) || inputs_index + this.read_delta <= this.inputs.length)
&& ((this.successes == null) || success_index < this.successes.length)) {
// Set up input values, if needed
for (int j = 0; j < this.read_delta; j++)
env.setObject(Env.encodeWriteVar(VarConstants.TYPE_OBJECT, j + this.read_offset_start),
this.inputs[j + inputs_index]);
if (this.successes == null
|| this.successes[success_index]) {
if (clone_reductor.succeed(env))
break;
}
// march forward, skipping entries processed by other reductor instances
success_index += reductors_nr;
inputs_index += this.read_delta * reductors_nr;
}
if (reductors_nr == 1) {
success = clone_reductor.eval(env);
check_result(clone_reductor, success);
}
if (reductors_nr > 1)
main_reductor.absorbAggregate(clone_reductor.getAggregate());
}
if (reductors_nr > 1)
check_result(main_reductor, main_reductor.eval(env));
}
public void
testReductorCountChunked(int reductors_nr)
{
final Reductor main_reductor = reductor;
main_reductor.setup(env);
// set up input variables
for (int i = reductor.getOuterReadArgsNr(); i < reductor.getReadArgsNr(); i++)
reductor.setArg(i, Env.encodeReadVar(VarConstants.TYPE_OBJECT, i));
for (int i = reductor.getReadArgsNr(); i < reductor.getArgsNr(); i++)
reductor.setArg(i, Env.encodeWriteVar(VarConstants.TYPE_OBJECT, i));
Reductor[] clone_reductors = new Reductor[reductors_nr];
for (int i = 0; i < reductors_nr; i++)
clone_reductors[i] = main_reductor.copy();
boolean[] clone_aborts = new boolean[reductors_nr];
for (int i = 0; i < reductors_nr; i++)
clone_aborts[i] = false;
int inputs_index = 0;
int success_index = 0;
int clone_nr = 0;
while (((this.inputs == null) || inputs_index + this.read_delta <= this.inputs.length)
&& ((this.successes == null) || success_index < this.successes.length)) {
final Reductor clone_reductor = clone_reductors[clone_nr];
if (!clone_aborts[clone_nr]) {
// Set up input values, if needed
for (int j = 0; j < this.read_delta; j++)
env.setObject(Env.encodeWriteVar(VarConstants.TYPE_OBJECT, j + this.read_offset_start),
this.inputs[j + inputs_index]);
if (this.successes == null
|| this.successes[success_index]) {
if (clone_reductor.succeed(env))
clone_aborts[clone_nr] = true;
}
}
// march forward, skipping entries processed by other reductor instances
success_index += 1;
inputs_index += this.read_delta;
clone_nr = (clone_nr + 1) % reductors_nr;
}
// first, merge all odds to their preceding evens
for (int i = 1; i < reductors_nr; i += 2)
clone_reductors[i-1].absorbAggregate(clone_reductors[i].getAggregate());
// Now, sum up:
for (int i = 2; i < reductors_nr; i += 2)
clone_reductors[0].absorbAggregate(clone_reductors[i].getAggregate());
final boolean success = clone_reductors[0].eval(env);
check_result(clone_reductors[0], success);
}
}
}