/**
* 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.flatten;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import org.diqube.context.Profiles;
import org.diqube.data.column.AdjustableStandardColumnShard;
import org.diqube.data.column.ColumnPage;
import org.diqube.data.column.ColumnType;
import org.diqube.data.column.StandardColumnShard;
import org.diqube.data.flatten.FlattenedTable;
import org.diqube.data.table.Table;
import org.diqube.data.table.TableFactory;
import org.diqube.data.table.TableShard;
import org.diqube.loader.JsonLoader;
import org.diqube.loader.LoadException;
import org.diqube.loader.LoaderColumnInfo;
import org.diqube.util.BigByteBuffer;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
/**
*
* @author Bastian Gloeckle
*/
public class FlattenedTableUtilTest {
private static final String TABLE = "testTable";
private AnnotationConfigApplicationContext dataContext;
private FlattenedTableUtil flattenedTableUtil;
private JsonLoader loader;
private TableFactory tableFactory;
private Flattener flattener;
@BeforeMethod
public void before() {
dataContext = new AnnotationConfigApplicationContext();
dataContext.getEnvironment().setActiveProfiles(Profiles.UNIT_TEST);
dataContext.scan("org.diqube");
dataContext.refresh();
flattenedTableUtil = dataContext.getBean(FlattenedTableUtil.class);
loader = dataContext.getBean(JsonLoader.class);
tableFactory = dataContext.getBean(TableFactory.class);
flattener = dataContext.getBean(Flattener.class);
}
@AfterMethod
public void after() {
dataContext.close();
}
@Test
public void adjustRowIdsDoesNotAffectOriginal() throws LoadException {
// GIVEN
String json = "[ { " //
+ "\"a\": [ "//
/* */ + "{ \"b\": 1, \"d\":[99, 100] }, "//
/* */ + "{ \"b\": 2, \"d\":[] }"//
+ "]" + //
",\"c\" : [ 9, 10 ] }," //
//
+ "{ " //
+ "\"a\": [ "//
/* */ + "{ \"b\": 3, \"d\":[300,301,302] }, "//
/* */ + "{ \"b\": 4, \"d\":[303,304,305] }, "//
/* */ + "{ \"b\": 5, \"d\":[306,307,308] } "//
+ "]" + ",\"c\" : [ 0 ]}" + " ]";
Table origTable = loadFromJson(100L, json);
FlattenedTable flattenedTable = flattener.flattenTable(origTable, null, "a[*]", UUID.randomUUID());
// assume flattenedTable was rowId-adjusted.
for (StandardColumnShard colShard : flattenedTable.getShards().iterator().next().getColumns().values()) {
((AdjustableStandardColumnShard) colShard).adjustToFirstRowId(200L);
}
// WHEN
FlattenedTable facadedTable =
flattenedTableUtil.facadeWithDefaultRowIds(flattenedTable, TABLE, "a[*]", UUID.randomUUID());
// THEN
Assert.assertEquals(flattenedTable.getShards().size(), 1L, "Expected correct flattened shards size.");
assertValidFirstRowId(flattenedTable.getShards().iterator().next(), 200L);
Assert.assertEquals(facadedTable.getShards().size(), 1L, "Expected correct facaded shards size.");
assertValidFirstRowId(facadedTable.getShards().iterator().next(), 100L);
// WHEN adjust firstRowId in facade
for (StandardColumnShard colShard : facadedTable.getShards().iterator().next().getColumns().values()) {
((AdjustableStandardColumnShard) colShard).adjustToFirstRowId(500L);
}
// THEN
assertValidFirstRowId(flattenedTable.getShards().iterator().next(), 200L); // flattenedTable did not change.
assertValidFirstRowId(facadedTable.getShards().iterator().next(), 500L);
}
private void assertValidFirstRowId(TableShard tableShard, long firstRowId) {
Assert.assertEquals(tableShard.getLowestRowId(), firstRowId,
"Table shard should have same firstRowId as original.");
Set<Long> allColumnShardsFirstRowId =
tableShard.getColumns().values().stream().map(colShard -> colShard.getFirstRowId()).collect(Collectors.toSet());
Assert.assertEquals(allColumnShardsFirstRowId, new HashSet<>(Arrays.asList(firstRowId)),
"Each col shard should have the same firstRowId");
for (StandardColumnShard colShard : tableShard.getColumns().values()) {
long nextFirstRowId = firstRowId;
for (ColumnPage page : colShard.getPages().values()) {
Assert.assertEquals(page.getFirstRowId(), nextFirstRowId, "Expected correct firstRowId for pages of column "
+ colShard.getName() + ", inspected page " + page.getName());
nextFirstRowId += page.size();
}
}
}
private Table loadFromJson(long firstRowId, String json) throws LoadException {
BigByteBuffer jsonBuffer = new BigByteBuffer(json.getBytes(Charset.forName("UTF-8")));
TableShard shard =
loader.load(firstRowId, jsonBuffer, TABLE, new LoaderColumnInfo(ColumnType.LONG)).iterator().next();
return tableFactory.createDefaultTable(TABLE, Arrays.asList(shard));
}
}