Package org.syncany.tests.util

Source Code of org.syncany.tests.util.TestAssertUtil

/*
* Syncany, www.syncany.org
* Copyright (C) 2011-2014 Philipp C. Heckel <philipp.heckel@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.syncany.tests.util;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.junit.internal.ArrayComparisonFailure;
import org.syncany.chunk.Transformer;
import org.syncany.database.ChunkEntry;
import org.syncany.database.DatabaseConnectionFactory;
import org.syncany.database.DatabaseVersion;
import org.syncany.database.FileContent;
import org.syncany.database.FileVersionComparator;
import org.syncany.database.FileVersionComparator.FileChange;
import org.syncany.database.FileVersionComparator.FileProperties;
import org.syncany.database.FileVersionComparator.FileVersionComparison;
import org.syncany.database.MemoryDatabase;
import org.syncany.database.MultiChunkEntry;
import org.syncany.database.PartialFileHistory;
import org.syncany.database.VectorClock;
import org.syncany.util.CollectionUtil;
import org.syncany.util.FileUtil;
import org.syncany.util.StringUtil;

import com.google.common.collect.Lists;

public class TestAssertUtil {
  private static final Logger logger = Logger.getLogger(TestAssertUtil.class.getSimpleName());
 
  public static void assertCollectionEquals(String message, Collection<? extends Object> expected, Collection<? extends Object> actual) {
    assertEquals(message+": Different amount of objects.", expected.size(), actual.size());
   
    Iterator<? extends Object> expectedIt = expected.iterator();
    Iterator<? extends Object> actualIt = actual.iterator();
   
    int i = 0;
    while (expectedIt.hasNext()) {     
      Object expectedObj = expectedIt.next();     
      Object actualObj = actualIt.next();
     
      assertEquals(message+": actual["+i+"] differs from expected["+i+"]: ", expectedObj, actualObj);
      i++;
    }
  }

  public static void assertFileListEqualsExcludeLockedAndNoRead(File expectedFilesRoot, File actualFilesRoot) throws ArrayComparisonFailure, Exception {
    Map<String, File> expectedFiles = TestFileUtil.getLocalFilesExcludeLockedAndNoRead(expectedFilesRoot);
    Map<String, File> actualFiles = TestFileUtil.getLocalFilesExcludeLockedAndNoRead(actualFilesRoot);
   
    assertFileListEquals("File list does not match", expectedFiles, actualFiles);
  }
 
  public static void assertFileListEquals(Map<String, File> expectedFiles, Map<String, File> actualFiles) throws ArrayComparisonFailure, Exception {
    assertFileListEquals("File list does not match", expectedFiles, actualFiles);
  }
 
  public static void assertFileListEquals(String message, Map<String, File> expectedFiles, Map<String, File> actualFiles) throws ArrayComparisonFailure, Exception {
    assertCollectionEquals("Actual file list ("+actualFiles.size()+" entries) differs from expected file list ("+expectedFiles.size()+" entries)", expectedFiles.keySet(), actualFiles.keySet());

    for (Map.Entry<String, File> expectedFileEntry : expectedFiles.entrySet()) {
      File expectedFile = expectedFileEntry.getValue();
      File actualFile = actualFiles.remove(expectedFileEntry.getKey());
     
      assertFileEquals(expectedFile, actualFile);
    }   
  }
 
  public static void assertConflictingFileExists(String originalFile, Map<String, File> actualFiles) {
    String fileNameWithoutExtention = TestFileUtil.getBasename(originalFile);
    Pattern conflictFilePattern = Pattern.compile(fileNameWithoutExtention + ".*conflicted.*");
   
    boolean conflictingFileFound = false;

    for (Map.Entry<String, File> actualFileEntry : actualFiles.entrySet()) {
      File actualFile = actualFileEntry.getValue();
      Matcher matcher = conflictFilePattern.matcher(actualFile.getName());

      if(matcher.matches()) {
        conflictingFileFound = true;
        break;
      }
    }   
    assertTrue("Pattern " + conflictFilePattern + " could not be found.",conflictingFileFound);
  }
 
  public static void assertFileEquals(File expectedFile, File actualFile) throws ArrayComparisonFailure, Exception {
    assertFileEquals(expectedFile, actualFile, new FileChange[] { FileChange.CHANGED_PATH });
  }
 
  public static void assertFileEquals(File expectedFile, File actualFile, FileChange... allowedChanges) throws ArrayComparisonFailure, Exception {   
    if (expectedFile == null && actualFile == null) {
      return;
    }
   
    assertNotNull("Files are not equal: Actual file is "+actualFile+", expected file is null.", expectedFile);
    assertNotNull("Files are not equal: Expected file is "+expectedFile+", actual file is null.", actualFile);
   
    Path root = Paths.get(actualFile.getAbsolutePath()).getRoot();
    FileVersionComparator fileVersionComparator = new FileVersionComparator(root.toFile(), "SHA1");
   
    if (!FileUtil.exists(expectedFile)) {
      fail("Files are not equal: Expected file "+expectedFile+" does not exist.");
    }
   
    if (!FileUtil.exists(actualFile)) {
      fail("Files are not equal: Actual file "+actualFile+" does not exist.");
    }

    if (FileUtil.isSymlink(actualFile) && FileUtil.isSymlink(expectedFile)) {
      return;
    }
   
    if (actualFile.isDirectory() != expectedFile.isDirectory()) {
      fail("Files are not equal: Comparing a directory with a file (actual is dir = "+actualFile.isDirectory()+", expected is dir = "+expectedFile.isDirectory()+")");
    }
   
    if (actualFile.isDirectory() && expectedFile.isDirectory()) {
      return;
    }
   
    if (actualFile.length() != expectedFile.length()) {
      fail("Files are not equal: Actual file size ("+actualFile+" = "+actualFile.length()+") does not match expected file size ("+expectedFile+" = "+expectedFile.length()+")");
    }
   
    byte[] expectedFileChecksum = TestFileUtil.createChecksum(expectedFile);
    byte[] actualFileChecksum = TestFileUtil.createChecksum(actualFile);
   
    assertArrayEquals("Files are not equal: Actual file checksum ("+StringUtil.toHex(actualFileChecksum)+") and expected file checksum ("+StringUtil.toHex(expectedFileChecksum)+") do not match.", expectedFileChecksum, actualFileChecksum);
   
    FileProperties actualFileProperties = fileVersionComparator.captureFileProperties(actualFile, null, true);
    FileProperties expectedFileProperties = fileVersionComparator.captureFileProperties(expectedFile, null, true);
   
    FileVersionComparison fileVersionComparison = fileVersionComparator.compare(expectedFileProperties, actualFileProperties, true);
   
    List<FileChange> allowedChangesList = new ArrayList<FileChange>(Arrays.asList(allowedChanges));
    allowedChangesList.add(FileChange.CHANGED_PATH);
   
    if (!CollectionUtil.containsOnly(fileVersionComparison.getFileChanges(), allowedChangesList)) {
      fail("Files are not equal: Actual file differs from expected file: "+fileVersionComparison.getFileChanges());
    }   
  }
 
  public static void assertSqlResultEquals(File databaseFile, String sqlQuery, String expectedResultStr) throws SQLException {
    Connection databaseConnection = DatabaseConnectionFactory.createConnection(databaseFile);   
    ResultSet resultSet = databaseConnection.prepareStatement(sqlQuery).executeQuery();
   
    List<String> actualResultStrList = new ArrayList<String>();   
   
    while (resultSet.next()) {
      for (int i=1; i<=resultSet.getMetaData().getColumnCount(); i++) {
        actualResultStrList.add(resultSet.getString(i));
      }
    }
   
    String actualResultStr = StringUtil.join(actualResultStrList, ",");
    assertEquals("SQL query result differs: "+sqlQuery, expectedResultStr, actualResultStr);
  }
 
  public static void assertSqlDatabaseEquals(File expectedDatabaseFile, File actualDatabaseFile) throws IOException, SQLException {
    // Compare tables + ignore columns
    String[][] compareTablesAndIgnoreColumns = new String[][] {
      new String[] { "chunk", "DATABASEVERSION_ID" },
      new String[] { "databaseversion", "ID" },
      new String[] { "databaseversion_vectorclock", "DATABASEVERSION_ID" },
      new String[] { "filecontent", "DATABASEVERSION_ID"},
      new String[] { "filecontent_chunk" },
      new String[] { "filehistory", "DATABASEVERSION_ID" },
      new String[] { "fileversion", "DATABASEVERSION_ID" },
        // skipped known_databases
      new String[] { "multichunk", "DATABASEVERSION_ID" },
      new String[] { "multichunk_chunk" }
    };
   
    assertSqlDatabaseTablesEqual(expectedDatabaseFile, actualDatabaseFile, compareTablesAndIgnoreColumns);
  }
 
  public static void assertSqlDatabaseTablesEqual(File expectedDatabaseFile, File actualDatabaseFile, String[]... compareTablesAndIgnoreColumns) throws IOException, SQLException {
    Connection expectedDatabaseConnection = DatabaseConnectionFactory.createConnection(expectedDatabaseFile);
    Connection actualDatabaseConnection = DatabaseConnectionFactory.createConnection(actualDatabaseFile);
       
    for (String[] tableNameAndIgnoreColumns : compareTablesAndIgnoreColumns) {
      String tableName = tableNameAndIgnoreColumns[0];
     
      List<String> ignoreColumnNames = Lists.newArrayList(tableNameAndIgnoreColumns);
      ignoreColumnNames.remove(0);
         
      // Get table's primary keys
      List<String> primaryKeys = new ArrayList<String>();     
      ResultSet resultSet = actualDatabaseConnection.getMetaData().getPrimaryKeys(null, null, tableName.toUpperCase());
     
      while (resultSet.next()) {
        primaryKeys.add(resultSet.getString("COLUMN_NAME"));
      }
     
      // Get table's columns
      List<String> tableColumns = new ArrayList<String>();
      resultSet = actualDatabaseConnection.getMetaData().getColumns(null, null, tableName.toUpperCase(), null);
     
      while (resultSet.next()) {
        String columnName = resultSet.getString("COLUMN_NAME");
       
        if (!ignoreColumnNames.contains(columnName)) {
          tableColumns.add(columnName);
        }
      }
     
      // Get all entries of both tables, sorted by the primary keys
      String columnNameList = StringUtil.join(tableColumns, ", ");
      String primaryKeysOrderByClause = StringUtil.join(primaryKeys, " asc, ") + " asc";
      String selectQuery = String.format("select %s from %s order by %s", columnNameList, tableName, primaryKeysOrderByClause);
     
      logger.log(Level.FINE, " Comparing database table: " + selectQuery);
     
      ResultSet expectedResultSet = expectedDatabaseConnection.prepareStatement(selectQuery).executeQuery();
      ResultSet actualResultSet = actualDatabaseConnection.prepareStatement(selectQuery).executeQuery();
     
      while (true) {
        boolean expectedNext = expectedResultSet.next();
        boolean actualNext = actualResultSet.next();
       
        if (expectedNext && !actualNext) {
          fail("Table "+tableName+": Actual is missing the following row from expected: "+getFormattedColumn(expectedResultSet));
        }
        else if (!expectedNext && actualNext) {
          fail("Table "+tableName+": Actual has a row that was not expected: "+getFormattedColumn(actualResultSet));
        }
        else if (!expectedNext && !actualNext) {
          break;
        }
        else {
          String expectedFormattedColumn = getFormattedColumn(expectedResultSet);
          String actualFormattedColumn = getFormattedColumn(actualResultSet);         
         
          assertEquals("Table "+tableName+": Columns of actual and expected differ.", expectedFormattedColumn, actualFormattedColumn);
        }               
      }   
    }
  }
 
  private static String getFormattedColumn(ResultSet resultSet) throws SQLException {
    ResultSetMetaData metaData = resultSet.getMetaData();
    List<String> formattedColumnLine = new ArrayList<String>();
   
    for (int i=0; i<metaData.getColumnCount(); i++) {
      formattedColumnLine.add(metaData.getColumnName(i+1) + "=" + resultSet.getString(i+1));
    }
   
    return StringUtil.join(formattedColumnLine, ", ");
  }

  public static void assertXmlDatabaseFileEquals(File expectedDatabaseFile, File actualDatabaseFile, Transformer transformer) throws IOException {   
    MemoryDatabase expectedDatabase = TestDatabaseUtil.readDatabaseFileFromDisk(expectedDatabaseFile, transformer);
    MemoryDatabase actualDatabase = TestDatabaseUtil.readDatabaseFileFromDisk(actualDatabaseFile, transformer);
   
    assertDatabaseEquals(expectedDatabase, actualDatabase);
  }

  public static void assertDatabaseEquals(MemoryDatabase expectedDatabase, MemoryDatabase actualDatabase) {
    logger.log(Level.INFO, "--");
    logger.log(Level.INFO, "Now comparing two databases.");
    logger.log(Level.INFO, "DON'T WORRY. This can take a long time or even overload the heap space.");
   
    List<DatabaseVersion> writtenDatabaseVersions = expectedDatabase.getDatabaseVersions();
    List<DatabaseVersion> readDatabaseVersions = actualDatabase.getDatabaseVersions();
   
    assertEquals("Different number of database versions.", writtenDatabaseVersions.size(), readDatabaseVersions.size());
     
    for (DatabaseVersion writtenDatabaseVersion : writtenDatabaseVersions) {
      DatabaseVersion readDatabaseVersion = null;
     
      for (DatabaseVersion aReadDatabaseVersion : readDatabaseVersions) {
        if (aReadDatabaseVersion.equals(writtenDatabaseVersion)) {
          readDatabaseVersion = aReadDatabaseVersion;
          break;
        }
      }
     
      assertNotNull("Database version "+writtenDatabaseVersion+" does not exist in read database.", readDatabaseVersion);
     
      assertDatabaseVersionEquals(writtenDatabaseVersion, readDatabaseVersion);
    }

    logger.log(Level.INFO, "End of comparing databases");   
    logger.log(Level.INFO, "--");   
 
 
  public static void assertDatabaseVersionEquals(DatabaseVersion expectedDatabaseVersion, DatabaseVersion actualDatabaseVersion) {
    assertVectorClockEquals(expectedDatabaseVersion.getVectorClock(), actualDatabaseVersion.getVectorClock());
    compareDatabaseVersionChunks(expectedDatabaseVersion.getChunks(), actualDatabaseVersion.getChunks());
    compareDatabaseVersionMultiChunks(expectedDatabaseVersion.getMultiChunks(), actualDatabaseVersion.getMultiChunks());
    compareDatabaseVersionFileContents(expectedDatabaseVersion.getFileContents(), actualDatabaseVersion.getFileContents());
    compareDatabaseVersionFileHistories(expectedDatabaseVersion.getFileHistories(), actualDatabaseVersion.getFileHistories())
  }   

  public static void assertVectorClockEquals(VectorClock expectedVectorClock, VectorClock actualVectorClock) {
    assertEquals("Vector clocks differ.", expectedVectorClock, actualVectorClock);   
  }

  private static void compareDatabaseVersionChunks(Collection<ChunkEntry> writtenChunks, Collection<ChunkEntry> readChunks) { 
    assertEquals("Different amount of Chunk objects.", writtenChunks.size(), readChunks.size());
    assertTrue("Chunk objects in written/read database version different.", writtenChunks.containsAll(readChunks));
    //assertCollectionEquals("Chunk objects in written/read database version different.", writtenChunks, readChunks);
  }
 
  private static void compareDatabaseVersionMultiChunks(Collection<MultiChunkEntry> writtenMultiChunks, Collection<MultiChunkEntry> readMultiChunks) {
    assertEquals("Different amount of MultiChunk objects.", writtenMultiChunks.size(), readMultiChunks.size());
    assertTrue("MultiChunk objects in written/read database version different.", writtenMultiChunks.containsAll(readMultiChunks));
    //assertCollectionEquals("MultiChunk objects in written/read database version different.", writtenMultiChunks, readMultiChunks);
 
 
  private static void compareDatabaseVersionFileContents(Collection<FileContent> writtenFileContents, Collection<FileContent> readFileContents) {
    assertEquals("Different amount of FileContent objects.", writtenFileContents.size(), readFileContents.size());
    assertTrue("FileContent objects in written/read database version different.", writtenFileContents.containsAll(readFileContents));
    //assertCollectionEquals("FileContent objects in written/read database version different.", writtenFileContents, readFileContents);
 

  private static void compareDatabaseVersionFileHistories(Collection<PartialFileHistory> writtenFileHistories, Collection<PartialFileHistory> readFileHistories) {
    assertTrue("FileHistory objects in written/read database version different.", writtenFileHistories.containsAll(readFileHistories));
 
 
  public static void assertErrorStackTraceContains(String expectedContains, Exception e) {
    StringWriter errors = new StringWriter();
    e.printStackTrace(new PrintWriter(errors));
   
    String stackTrace = errors.toString();
   
    if (stackTrace.contains(expectedContains)) {
      return;
    }
   
    e.printStackTrace();
    fail("Stack trace expected to contain " + expectedContains);
  }
 
  public static void assertRegexInLines(String expectedLinePattern, String[] lines) {
    Pattern expectedPattern = Pattern.compile(expectedLinePattern);
   
    for (String line : lines) {
      if (expectedPattern.matcher(line).find()) {
        return;
      }
    }
   
    fail("Output does not contain "+ expectedLinePattern);
  }
}
TOP

Related Classes of org.syncany.tests.util.TestAssertUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.