/**
* diqube: Distributed Query Base.
*
* Copyright (C) 2015 Bastian Gloeckle
*
* This file is part of diqube.
*
* diqube is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.diqube.executionenv.util;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.diqube.data.types.lng.dict.LongDictionary;
import org.diqube.executionenv.ExecutionEnvironment;
import org.diqube.executionenv.querystats.QueryableLongColumnShard;
import org.diqube.executionenv.util.ColumnPatternUtil.ColumnPatternContainer;
import org.diqube.executionenv.util.ColumnPatternUtil.PatternException;
import org.diqube.name.RepeatedColumnNameGenerator;
import org.diqube.util.Triple;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
* Tests {@link ColumnPatternUtil}.
*
* @author Bastian Gloeckle
*/
public class ColumnPatternUtilTest {
private ColumnPatternUtil colPatternUtil;
private ExecutionEnvironment env;
@BeforeMethod
public void before() {
colPatternUtil = new ColumnPatternUtil();
colPatternUtil.setRepeatedColNames(new RepeatedColumnNameGenerator());
env = Mockito.mock(ExecutionEnvironment.class);
}
@Test
public void singlePatternSimple() {
// GIVEN
simulateLengths(new Triple<>("a.b", 5L, 2L));
// WHEN
ColumnPatternContainer patterns = colPatternUtil.findColNamesForColNamePattern(env, "a.b[*].c");
Set<List<String>> res = patterns.getColumnPatterns(1L);
// THEN
Set<List<String>> expected = new HashSet<>(Arrays.asList(Arrays.asList("a.b[0].c"), Arrays.asList("a.b[1].c")));
Assert.assertEquals(res, expected, "Expected correct final colNames");
}
@Test
public void singlePatternSimple2() {
// GIVEN
simulateLengths(new Triple<>("a.b", 3L, 2L), //
new Triple<>("a.b[0].c", 7L, 1L), //
new Triple<>("a.b[1].c", 3L, 3L), //
new Triple<>("a.b[2].c", 1L, 0L));
// WHEN
ColumnPatternContainer patterns = colPatternUtil.findColNamesForColNamePattern(env, "a.b[*].c[*]");
Set<List<String>> res = patterns.getColumnPatterns(1L);
// THEN
Set<List<String>> expected = new HashSet<>(Arrays.asList( //
Arrays.asList("a.b[0].c[0]"), //
Arrays.asList("a.b[1].c[0]"), //
Arrays.asList("a.b[1].c[1]"), //
Arrays.asList("a.b[1].c[2]")));
Assert.assertEquals(res, expected, "Expected correct final colNames");
}
@Test(expectedExceptions = PatternException.class)
public void singlePatternNone() {
// GIVEN
// WHEN
colPatternUtil.findColNamesForColNamePattern(env, "a.b[1].c[0]");
// THEN: PatternException (no [*])
}
@Test
public void multiplePatternSimple() {
// GIVEN
simulateLengths(new Triple<>("a.b", 5L, 2L));
// GIVEN WHEN
ColumnPatternContainer patterns =
colPatternUtil.findColNamesForColNamePattern(env, Arrays.asList("a.b[*].c", "a.b[*].d"));
Set<List<String>> res = patterns.getColumnPatterns(1L);
// THEN
Set<List<String>> expected = new HashSet<>(Arrays.asList(Arrays.asList("a.b[0].c", "a.b[0].d"), //
Arrays.asList("a.b[1].c", "a.b[1].d")));
Assert.assertEquals(res, expected, "Expected correct final colNames");
}
@Test(expectedExceptions = PatternException.class)
public void multiplePatternWrongRepetition() {
// GIVEN WHEN
colPatternUtil.findColNamesForColNamePattern(env, Arrays.asList("a.b[*].c", "a.c[*].d[*]"));
// THEN - exception
}
@Test
public void multiplePatternTwoLevel() {
// GIVEN
simulateLengths(new Triple<>("a.b", 3L, 3L), //
new Triple<>("a.b[0].d", 7L, 3L), //
new Triple<>("a.b[1].d", 2L, 1L), //
new Triple<>("a.b[2].d", 1L, 0L));
// WHEN
ColumnPatternContainer patterns =
colPatternUtil.findColNamesForColNamePattern(env, Arrays.asList("a.b[*].c", "a.b[*].d[*].e"));
Set<List<String>> res = patterns.getColumnPatterns(1L);
// THEN
Set<List<String>> expected = new HashSet<>(Arrays.asList( //
Arrays.asList("a.b[0].c", "a.b[0].d[0].e"), //
Arrays.asList("a.b[0].c", "a.b[0].d[1].e"), //
Arrays.asList("a.b[0].c", "a.b[0].d[2].e"), //
Arrays.asList("a.b[1].c", "a.b[1].d[0].e") //
));
Assert.assertEquals(res, expected, "Expected correct final colNames");
}
@Test
public void multiplePatternTwoLevel2() {
// GIVEN
simulateLengths(new Triple<>("a", 3L, 2L), //
new Triple<>("a[0].b.c", 3L, 2L), //
new Triple<>("a[1].b.c", 3L, 1L), //
new Triple<>("a[2].b.c", 1L, 1L) //
);
// WHEN
ColumnPatternContainer patterns =
colPatternUtil.findColNamesForColNamePattern(env, Arrays.asList("a[*].b.c[*]", "a[*].b.d"));
Set<List<String>> res = patterns.getColumnPatterns(1L);
// THEN
Set<List<String>> expected = new HashSet<>(Arrays.asList( //
Arrays.asList("a[0].b.c[0]", "a[0].b.d"), //
Arrays.asList("a[0].b.c[1]", "a[0].b.d"), //
Arrays.asList("a[1].b.c[0]", "a[1].b.d") //
));
Assert.assertEquals(res, expected, "Expected correct final colNames");
}
@Test
public void multiplePatternTwoLevel3() {
// GIVEN
simulateLengths(new Triple<>("a", 3L, 2L), //
new Triple<>("a[0].b.c", 3L, 2L), //
new Triple<>("a[1].b.c", 3L, 1L), //
new Triple<>("a[2].b.c", 3L, 2L) //
);
// WHEN
ColumnPatternContainer patterns =
colPatternUtil.findColNamesForColNamePattern(env, Arrays.asList("a[*].b.c[*]", "a[*].b.c[*]"));
Set<List<String>> res = patterns.getColumnPatterns(1L);
// THEN
Set<List<String>> expected = new HashSet<>(Arrays.asList( //
Arrays.asList("a[0].b.c[0]", "a[0].b.c[0]"), //
Arrays.asList("a[0].b.c[1]", "a[0].b.c[1]"), //
Arrays.asList("a[1].b.c[0]", "a[1].b.c[0]")));
Assert.assertEquals(res, expected, "Expected correct final colNames");
}
@Test
public void multiplePatternTwoAndNone() {
// GIVEN
simulateLengths(new Triple<>("a", 3L, 2L), //
new Triple<>("a[0].b.c", 3L, 2L), //
new Triple<>("a[1].b.c", 3L, 1L), //
new Triple<>("a[2].b.c", 3L, 2L) //
);
// WHEN
ColumnPatternContainer patterns =
colPatternUtil.findColNamesForColNamePattern(env, Arrays.asList("a[*].b.c[*]", "a.x"));
Set<List<String>> res = patterns.getColumnPatterns(1L);
// THEN
Set<List<String>> expected = new HashSet<>(Arrays.asList( //
Arrays.asList("a[0].b.c[0]", "a.x"), //
Arrays.asList("a[0].b.c[1]", "a.x"), //
Arrays.asList("a[1].b.c[0]", "a.x")));
Assert.assertEquals(res, expected, "Expected correct final colNames");
}
/**
* @param lengths
* Triple of "colName", "maxLen", "len of requested row".
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@SafeVarargs
private final void simulateLengths(Triple<String, Long, Long>... lengths) {
for (Triple<String, Long, Long> lengthTriple : lengths) {
String colName = lengthTriple.getLeft();
long maxLen = lengthTriple.getMiddle();
long len = lengthTriple.getRight();
LongDictionary<?> colDictMock = Mockito.mock(LongDictionary.class);
Mockito.when(colDictMock.getMaxId()).thenReturn(Long.valueOf(Long.MIN_VALUE));
Mockito.when(colDictMock.decompressValue(Mockito.anyLong())).thenAnswer(new Answer<Long>() {
@Override
public Long answer(InvocationOnMock invocation) throws Throwable {
if (invocation.getArguments()[0].equals(Long.MIN_VALUE))
return Long.valueOf(maxLen);
return Long.valueOf(len);
}
});
QueryableLongColumnShard lenColMock = Mockito.mock(QueryableLongColumnShard.class, Mockito.RETURNS_MOCKS);
Mockito.when(lenColMock.getColumnShardDictionary()).thenReturn((LongDictionary) colDictMock);
// any value != Long.MIN_VALUE.
Mockito.when(lenColMock.resolveColumnValueIdForRow(Mockito.anyLong())).thenReturn(99L);
Mockito.when(env.getLongColumnShard(new RepeatedColumnNameGenerator().repeatedLength(colName)))
.thenReturn(lenColMock);
}
}
}