/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program 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 com.foundationdb.qp.storeadapter.indexcursor;
import static org.junit.Assert.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.junit.Before;
import org.junit.Test;
import com.foundationdb.qp.storeadapter.indexcursor.MergeJoinSorter.KeyReader;
import com.foundationdb.qp.storeadapter.indexcursor.MergeJoinSorter.KeyWriter;
import com.foundationdb.qp.storeadapter.indexcursor.MergeJoinSorter.SortKey;
import com.persistit.Key;
import com.persistit.KeyState;
import com.persistit.Persistit;
public class KeyReaderWriterTest {
private ByteArrayOutputStream os;
private ByteArrayInputStream is;
private SortKey startKey;
private Key testKey;
private KeyWriter writer;
@Before
public void createFileBuffers() {
os = new ByteArrayOutputStream();
startKey = new SortKey();
testKey = new Key ((Persistit)null);
writer = new KeyWriter(os);
}
@Test
public void cycleSimple() throws IOException {
testKey.append(1);
startKey.sortKeys.add(new KeyState(testKey));
startKey.rowValue.put(1);
writer.writeEntry(startKey);
verifyInput();
}
@Test
public void cycleString() throws IOException {
testKey.append("abcd");
startKey.sortKeys.add(new KeyState(testKey));
startKey.rowValue.put("abcd");
writer.writeEntry(startKey);
verifyInput();
}
@Test
public void cycleNIntegers() throws IOException {
for (int i = 0; i < 400; i++) {
testKey.append(i);
startKey.rowValue.put(i);
}
startKey.sortKeys.add(new KeyState(testKey));
writer.writeEntry(startKey);
verifyInput();
}
@Test
public void cycle2Keys() throws IOException {
testKey.append(1);
startKey.sortKeys.add(new KeyState(testKey));
startKey.rowValue.put(1);
writer.writeEntry(startKey);
writer.writeEntry(startKey);
is = new ByteArrayInputStream (os.toByteArray());
KeyReader reader = new KeyReader (is);
SortKey endKey = reader.readNext();
assertTrue (startKey.rowValue.get().equals(endKey.rowValue.get()));
assertTrue (startKey.sortKeys.get(0).compareTo(endKey.sortKeys.get(0)) == 0);
endKey = reader.readNext();
assertTrue (startKey.rowValue.get().equals(endKey.rowValue.get()));
assertTrue (startKey.sortKeys.get(0).compareTo(endKey.sortKeys.get(0)) == 0);
endKey = reader.readNext();
assertNull (endKey);
}
@Test
public void cycleNKeys() throws IOException{
List<SortKey> keys = new ArrayList<>(100);
for (int i = 0; i < 100; i++) {
SortKey newKey = new SortKey();
newKey.rowValue.put(i);
testKey.clear();
testKey.append(i);
newKey.sortKeys.add(new KeyState (testKey));
keys.add(newKey);
}
verifyNKeys (keys);
}
@Test
public void cycleNStrings() throws IOException {
List<SortKey> keys = new ArrayList<>(100);
for (int i = 0; i < 100; i++) {
SortKey newKey = new SortKey();
String value = characters(5+random.nextInt(1000));
newKey.rowValue.put(value);
testKey.clear();
testKey.append(value);
newKey.sortKeys.add(new KeyState (testKey));
keys.add(newKey);
}
verifyNKeys (keys);
}
@Test
public void cycleNMultiKeys () throws IOException {
List<SortKey> keys = new ArrayList<>(100);
for (int i = 0; i < 100; i++) {
SortKey newKey = new SortKey();
newKey.rowValue.setStreamMode(true);
newKey.rowValue.put(random.nextInt());
newKey.rowValue.putNull();
newKey.rowValue.put(characters(3+random.nextInt(25)));
newKey.rowValue.put(characters(3+random.nextInt(25)));
testKey.clear();
testKey.append(i);
newKey.sortKeys.add(new KeyState (testKey));
keys.add(newKey);
}
verifyNKeys(keys);
}
private void verifyInput() throws IOException {
is = new ByteArrayInputStream (os.toByteArray());
KeyReader reader = new KeyReader (is);
SortKey endKey = reader.readNext();
assertTrue (startKey.rowValue.get().equals(endKey.rowValue.get()));
assertTrue (startKey.sortKeys.get(0).compareTo(endKey.sortKeys.get(0)) == 0);
}
private void verifyNKeys(List<SortKey> keys) throws IOException {
for (SortKey key : keys) {
writer.writeEntry(key);
}
is = new ByteArrayInputStream (os.toByteArray());
KeyReader reader = new KeyReader (is);
SortKey endKey;
for (SortKey startKey : keys) {
endKey = reader.readNext();
endKey.rowValue.setStreamMode(true);
startKey.rowValue.setStreamMode(true);
assertTrue (startKey.rowValue.get().equals(endKey.rowValue.get()));
assertTrue (startKey.sortKeys.get(0).compareTo(endKey.sortKeys.get(0)) == 0);
}
}
static final String ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
final Random random = new Random(100);
public String characters(final int length) {
StringBuilder sb = new StringBuilder(length);
for( int i = 0; i < length; i++ )
sb.append(ALPHA.charAt(random.nextInt(ALPHA.length())));
return sb.toString();
}
}