/**
* This file is licensed under the University of Illinois/NCSA Open Source License. See LICENSE.TXT for details.
*/
package edu.illinois.codingtracker.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.Iterator;
import java.util.List;
import org.junit.Test;
import edu.illinois.codingtracker.helpers.ResourceHelper;
import edu.illinois.codingtracker.operations.OperationDeserializer;
import edu.illinois.codingtracker.operations.UserOperation;
/**
*
* @author Stas Negara
*
*/
public abstract class RecorderReplayerTest extends CodingTrackerTest {
private static final String TEST_FILES_FOLDER= "test-files";
private static final String CODECHANGES_FILE_NAME= "codechanges.txt";
protected abstract String getTestNumber();
protected abstract String[] getTestFileNames();
protected abstract String[] getGeneratedFilePaths();
@Test
public void shouldReplayAndRecord() {
List<UserOperation> predefinedUserOperations= loadTestUserOperations();
replayUserOperations(predefinedUserOperations);
List<UserOperation> generatedUserOperations= loadGeneratedUserOperations();
checkEquivalencyOfUserOperations(predefinedUserOperations, generatedUserOperations);
checkFinalCode();
}
private void checkEquivalencyOfUserOperations(List<UserOperation> predefinedUserOperations, List<UserOperation> generatedUserOperations) {
Iterator<UserOperation> generatedUserOperationsIterator= generatedUserOperations.iterator();
for (UserOperation predefinedUserOperation : predefinedUserOperations) {
//Skip those operations that are not recorded by the test
if (!predefinedUserOperation.isTestReplayRecorded()) {
continue;
}
assertTrue(generatedUserOperationsIterator.hasNext());
UserOperation generatedUserOperation= generatedUserOperationsIterator.next();
assertTrue(predefinedUserOperation.getClass() == generatedUserOperation.getClass());
assertEquals(removeVolatileParts(predefinedUserOperation), removeVolatileParts(generatedUserOperation));
}
assertFalse(generatedUserOperationsIterator.hasNext()); //there should be no other generated operations
}
private void checkFinalCode() {
String[] testFileNames= getTestFileNames();
String[] generatedFilePaths= getGeneratedFilePaths();
for (int i= 0; i < testFileNames.length; i++) {
File predefinedFile= getTestFile(testFileNames[i]);
File generatedFile= getGeneratedFile(generatedFilePaths[i]);
checkFilesAreEqual(predefinedFile, generatedFile);
}
}
private void checkFilesAreEqual(File file1, File file2) {
assertEquals(ResourceHelper.readFileContent(file1), ResourceHelper.readFileContent(file2));
}
private void replayUserOperations(List<UserOperation> userOperations) {
for (UserOperation userOperation : userOperations) {
try {
userOperation.replay();
} catch (Exception e) {
throw new RuntimeException("Could not replay operation: " + userOperation, e);
}
}
}
private List<UserOperation> loadTestUserOperations() {
return loadUserOperationsFromFile(getTestFile(CODECHANGES_FILE_NAME));
}
private List<UserOperation> loadGeneratedUserOperations() {
return loadUserOperationsFromFile(mainRecordFile);
}
private List<UserOperation> loadUserOperationsFromFile(File recordFile) {
String operationsRecord= ResourceHelper.readFileContent(recordFile);
return OperationDeserializer.getUserOperations(operationsRecord);
}
private File getTestFile(String fileName) {
String testFileName= TEST_FILES_FOLDER + "/" + getTestNumber() + "/" + fileName;
return new File(testFileName);
}
private File getGeneratedFile(String workspaceRelativeFilePath) {
return ResourceHelper.getFileForResource(ResourceHelper.findWorkspaceMember(workspaceRelativeFilePath));
}
private String removeVolatileParts(UserOperation userOperation) {
String userOperationString= userOperation.toString();
int timestampIndex= userOperationString.lastIndexOf("Timestamp: ");
String result= userOperationString.substring(0, timestampIndex);
int editorIDIndex= result.indexOf("Editor ID: ");
if (editorIDIndex != -1) {
int newLineIndex= result.indexOf("\n", editorIDIndex);
result= result.substring(0, editorIDIndex) + result.substring(newLineIndex);
}
return result;
}
}