package com.opendoorlogistics.core.tables.decorators.datastores.undoredo;
import java.util.Random;
import org.junit.Test;
import com.opendoorlogistics.api.tables.ODLColumnType;
import com.opendoorlogistics.api.tables.ODLDatastoreAlterable;
import com.opendoorlogistics.api.tables.ODLTableAlterable;
import com.opendoorlogistics.core.api.impl.ODLApiImpl;
import com.opendoorlogistics.core.tables.utils.DatastoreComparer;
import static org.junit.Assert.*;
public class TestUndoRedoDecoratorTrim {
private static String randomString(Random r, int len){
StringBuilder builder = new StringBuilder(len);
for(int i =0 ; i < len ; i++){
builder.append((char)('a' + (char)r.nextInt(26)));
}
return builder.toString();
}
private static class TesterTables{
final Random r;
final UndoRedoDecorator<ODLTableAlterable> undoRedoDecorator;
final ODLTableAlterable controlTable;
final ODLTableAlterable undoRedoTable;
final int minRows;
final int strLen;
int lastRow;
String lastString;
TesterTables(Random r, int nrows, int strLen,long bufferSizeBytes){
this.r=r;
this.minRows = nrows;
this.strLen = strLen;
// create and fill table
ODLApiImpl api = new ODLApiImpl();
ODLDatastoreAlterable<? extends ODLTableAlterable> ds = api.tables().createAlterableDs();
ODLTableAlterable table = ds.createTable("Test", -1);
table.addColumn(-1, "TEST", ODLColumnType.STRING, 0);
for(int i =0 ; i < nrows ; i++){
int row = table.createEmptyRow(-1);
table.setValueAt(randomString(r, strLen), row, 0);
}
// create decorator
undoRedoDecorator = new UndoRedoDecorator<ODLTableAlterable>(ODLTableAlterable.class, ds, bufferSizeBytes);
undoRedoTable = undoRedoDecorator.getTableAt(0);
// create copy
controlTable = (ODLTableAlterable)table.deepCopyWithShallowValueCopy();
}
void modifyUndoRedoTable(){
lastRow = r.nextInt(undoRedoTable.getRowCount());
lastString = randomString(r, strLen);
undoRedoTable.setValueAt(lastString, lastRow, 0);
}
void applyToControl(){
controlTable.setValueAt(lastString, lastRow, 0);
}
}
@Test
public void testTrim() {
int nrows = 25;
int strLen=100;
int nbTrims=100;
long bufferSizeBytes = 1024 * 100;
Random random = new Random(123);
TesterTables data = new TesterTables(random, nrows, strLen, bufferSizeBytes);
long minEstimatedMemoryUsed = 0;
long minTotalEstimatedUsed=0;
long nbLoops=0;
while(data.undoRedoDecorator.getTrimCount() < nbTrims){
long oldSizeBytes = data.undoRedoDecorator.getEstimatedBufferSizeInBytes();
long oldTrimCount= data.undoRedoDecorator.getTrimCount();
// modfy table and check (a) we have an and (b) its not the same as the control table
data.modifyUndoRedoTable();
assertTrue(data.undoRedoDecorator.hasUndo());
assertTrue(!DatastoreComparer.isSame(data.controlTable, data.undoRedoTable, 0));
// undo the change and check we have a redo and the datastores are the same again
data.undoRedoDecorator.undo();
assertTrue(data.undoRedoDecorator.hasRedo());
assertTrue(DatastoreComparer.isSame(data.controlTable, data.undoRedoTable, 0));
// clear the redo and check old size is the same as new
data.undoRedoDecorator.clearRedos();
assertTrue(oldSizeBytes == data.undoRedoDecorator.getEstimatedBufferSizeInBytes() || oldTrimCount != data.undoRedoDecorator.getTrimCount());
assertFalse(data.undoRedoDecorator.hasRedo());
// set it again
data.modifyUndoRedoTable();
data.applyToControl();
// update total used
long estimatedBytes =strLen*2;
minTotalEstimatedUsed += estimatedBytes;
long newSizeBytes = data.undoRedoDecorator.getEstimatedBufferSizeInBytes();
long newTrimCount = data.undoRedoDecorator.getTrimCount();
assertTrue(oldTrimCount <= newTrimCount);
if(oldTrimCount == newTrimCount){
minEstimatedMemoryUsed += estimatedBytes;
// no trim, so old size should be smaller
assertTrue(oldSizeBytes < newSizeBytes);
}
else{
minEstimatedMemoryUsed = estimatedBytes;
// trim happened, so old size should be larger
assertTrue(oldSizeBytes > newSizeBytes);
}
// we should never have less memory usage than our minimum estimation
assertTrue(data.undoRedoDecorator.getEstimatedBufferSizeInBytes() >= minEstimatedMemoryUsed);
// number of trims should always be above the minimum trim count
long minTrims = minTotalEstimatedUsed / bufferSizeBytes;
assertTrue(data.undoRedoDecorator.getTrimCount() >= minTrims);
nbLoops++;
}
}
}