Package org.syncany.tests.scenarios

Source Code of org.syncany.tests.scenarios.DirtyDatabaseScenarioTest

/*
* 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.scenarios;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.syncany.tests.util.TestAssertUtil.assertConflictingFileExists;
import static org.syncany.tests.util.TestAssertUtil.assertFileEquals;
import static org.syncany.tests.util.TestAssertUtil.assertFileListEquals;
import static org.syncany.tests.util.TestAssertUtil.assertSqlDatabaseEquals;

import java.util.Iterator;
import java.util.List;

import org.junit.Test;
import org.syncany.config.Config;
import org.syncany.database.DatabaseConnectionFactory;
import org.syncany.database.DatabaseVersion;
import org.syncany.database.PartialFileHistory;
import org.syncany.database.dao.ChunkSqlDao;
import org.syncany.database.dao.DatabaseVersionSqlDao;
import org.syncany.database.dao.FileContentSqlDao;
import org.syncany.database.dao.FileHistorySqlDao;
import org.syncany.database.dao.FileVersionSqlDao;
import org.syncany.database.dao.MultiChunkSqlDao;
import org.syncany.operations.ChangeSet;
import org.syncany.operations.cleanup.CleanupOperationOptions;
import org.syncany.operations.status.StatusOperationOptions;
import org.syncany.operations.status.StatusOperationResult;
import org.syncany.operations.up.UpOperationOptions;
import org.syncany.plugins.transfer.TransferSettings;
import org.syncany.tests.util.TestAssertUtil;
import org.syncany.tests.util.TestClient;
import org.syncany.tests.util.TestCollectionUtil;
import org.syncany.tests.util.TestConfigUtil;
import org.syncany.tests.util.TestSqlUtil;

public class DirtyDatabaseScenarioTest {
  @Test
  public void testDirtyDatabase() throws Exception {
    // Setup
    TransferSettings testConnection = TestConfigUtil.createTestLocalConnection();
   
    TestClient clientA = new TestClient("A", testConnection);
    TestClient clientB = new TestClient("B", testConnection);
   
    // Run
    UpOperationOptions upOptionsForceEnabled = new UpOperationOptions();
    upOptionsForceEnabled.setForceUploadEnabled(true);
   
    clientA.createNewFile("A-file1.jpg", 50*1024);
    clientA.up(upOptionsForceEnabled);
       
    clientB.createNewFile("A-file1.jpg", 51*1024);
    clientB.up(upOptionsForceEnabled);
   
    clientB.down(); // This creates a dirty database       
   
    // Test (for dirty database existence)
    Config configB = clientB.getConfig();
    java.sql.Connection databaseConnectionB = configB.createDatabaseConnection();

    ChunkSqlDao chunkDao = new ChunkSqlDao(databaseConnectionB);
    MultiChunkSqlDao multiChunkDao = new MultiChunkSqlDao(databaseConnectionB);
    FileVersionSqlDao fileVersionDao = new FileVersionSqlDao(databaseConnectionB);
    FileHistorySqlDao fileHistoryDao = new FileHistorySqlDao(databaseConnectionB, fileVersionDao);
    FileContentSqlDao fileContentDao = new FileContentSqlDao(databaseConnectionB);
    DatabaseVersionSqlDao databaseVersionDao = new DatabaseVersionSqlDao(databaseConnectionB, chunkDao, fileContentDao, fileVersionDao, fileHistoryDao, multiChunkDao);
   
    Iterator<DatabaseVersion> databaseVersionsDirtyB = databaseVersionDao.getDirtyDatabaseVersions();
    List<DatabaseVersion> databaseVersionsDirtyListB = TestCollectionUtil.toList(databaseVersionsDirtyB);
   
    assertEquals(1, databaseVersionsDirtyListB.size());
   
    DatabaseVersion dirtyDatabaseVersionB = databaseVersionsDirtyListB.get(0);
    assertNotNull(dirtyDatabaseVersionB);
    assertEquals(1, dirtyDatabaseVersionB.getFileHistories().size());
   
    PartialFileHistory fileHistoryFile1B = dirtyDatabaseVersionB.getFileHistories().iterator().next();   
    assertNotNull(fileHistoryFile1B);
    assertEquals(1, fileHistoryFile1B.getFileVersions().size());
    assertEquals("A-file1.jpg", fileHistoryFile1B.getLastVersion().getPath());
       
    assertFileEquals(clientA.getLocalFile("A-file1.jpg"), clientB.getLocalFile("A-file1.jpg"));
    assertConflictingFileExists("A-file1.jpg", clientB.getLocalFilesExcludeLockedAndNoRead());   
   
    // Run (part 2)
    clientB.up(); // This deletes the dirty database file
   
    Iterator<DatabaseVersion> databaseVersionsDirtyB2 = databaseVersionDao.getDirtyDatabaseVersions();
    List<DatabaseVersion> databaseVersionsDirtyListB2 = TestCollectionUtil.toList(databaseVersionsDirtyB2);
   
    assertEquals(0, databaseVersionsDirtyListB2.size());

    // Run (part 3)
    clientA.down(); // This pulls down the conflicting file
    assertFileListEquals(clientA.getLocalFilesExcludeLockedAndNoRead(), clientB.getLocalFilesExcludeLockedAndNoRead());
    assertSqlDatabaseEquals(clientA.getDatabaseFile(), clientB.getDatabaseFile());
    assertConflictingFileExists("A-file1.jpg", clientA.getLocalFilesExcludeLockedAndNoRead());
   
    // Tear down
    clientA.deleteTestData();
    clientB.deleteTestData();
  }

  @Test
  public void testDirtyCleanupDirty() throws Exception {
    // Setup
    TransferSettings testConnection = TestConfigUtil.createTestLocalConnection();
   
    TestClient clientA = new TestClient("A", testConnection);
    TestClient clientB = new TestClient("B", testConnection);
    TestClient clientC = new TestClient("C", testConnection);
    TestClient clientD = new TestClient("D", testConnection);
 
    StatusOperationOptions statusOptions = new StatusOperationOptions();
    statusOptions.setForceChecksum(true);
   
    UpOperationOptions upOptionsForceEnabled = new UpOperationOptions();
    upOptionsForceEnabled.setStatusOptions(statusOptions);
    upOptionsForceEnabled.setForceUploadEnabled(true);
   
    CleanupOperationOptions cleanupOptions = new CleanupOperationOptions();
    cleanupOptions.setMinSecondsBetweenCleanups(0);

    // Run
   
    //// 1. CREATE FIRST DIRTY VERSION
   
    clientA.createNewFile("A-file1.jpg", 50*1024);
    clientA.up(upOptionsForceEnabled); // (A1)
   
    clientB.down();
    clientB.changeFile("A-file1.jpg");;
    clientB.up(upOptionsForceEnabled); // (A1,B1)
       
    clientA.down();
   
    clientA.changeFile("A-file1.jpg")// conflict (winner)
    clientA.up(upOptionsForceEnabled); // (A2,B1)
   
    clientB.changeFile("A-file1.jpg"); // conflict (loser)
    clientB.up(upOptionsForceEnabled);
   
    clientA.createNewFolder("new folder at A"); // don't care about the conflict, just continue
    clientA.up(upOptionsForceEnabled); // (A3,B1)
   
    clientB.createNewFolder("new folder at B"); // don't care about the conflict, just continue
    clientB.up(upOptionsForceEnabled);
   
    clientA.down(); // resolve conflict (wins, no DIRTY)
   
    java.sql.Connection databaseConnectionA = DatabaseConnectionFactory.createConnection(clientA.getDatabaseFile());
    assertEquals("0", TestSqlUtil.runSqlSelect("select count(*) from databaseversion where status='DIRTY'", databaseConnectionA));
   
    clientB.down(); // resolve conflict (loses, creates DIRTY version)
   
    java.sql.Connection databaseConnectionB = DatabaseConnectionFactory.createConnection(clientB.getDatabaseFile());
    assertEquals("2", TestSqlUtil.runSqlSelect("select count(*) from databaseversion where status='DIRTY'", databaseConnectionB));
    assertEquals("(A1,B2)\n(A1,B3)", TestSqlUtil.runSqlSelect("select vectorclock_serialized from databaseversion where status='DIRTY' order by id", databaseConnectionB));
    assertEquals("(A1)\n(A1,B1)\n(A2,B1)\n(A3,B1)", TestSqlUtil.runSqlSelect("select vectorclock_serialized from databaseversion where status<>'DIRTY' order by id", databaseConnectionB));
   
    StatusOperationResult statusResultBAfterDirty = clientB.status();
    assertNotNull(statusResultBAfterDirty);
   
    ChangeSet changeSetBAfterDirty = statusResultBAfterDirty.getChangeSet();   
    assertEquals(2, changeSetBAfterDirty.getNewFiles().size());
    TestAssertUtil.assertConflictingFileExists("A-file1.jpg", clientB.getLocalFiles());
   
    clientB.up(upOptionsForceEnabled); // (A3,B2)
    assertEquals("0", TestSqlUtil.runSqlSelect("select count(*) from databaseversion where status='DIRTY'", databaseConnectionB));
   
    assertEquals("4", TestSqlUtil.runSqlSelect("select count(*) from databaseversion", databaseConnectionA)); // (A1), (A1,B1), (A2,B1), (A3,B1)
    assertEquals("(A1)\n(A1,B1)\n(A2,B1)\n(A3,B1)", TestSqlUtil.runSqlSelect("select vectorclock_serialized from databaseversion order by id", databaseConnectionA));
   
    assertEquals("5", TestSqlUtil.runSqlSelect("select count(*) from databaseversion", databaseConnectionB));
    assertEquals("(A1)\n(A1,B1)\n(A2,B1)\n(A3,B1)\n(A3,B4)", TestSqlUtil.runSqlSelect("select vectorclock_serialized from databaseversion order by id", databaseConnectionB));

   
    //// 2. NOW THAT CLIENT B RESOLVED IT, A GETS DIRTY
   
    clientA.changeFile("A-file1.jpg"); // No 'down'! This version will become DIRTY
    clientA.createNewFile("dirty1");
    clientA.up(upOptionsForceEnabled);
   
    clientA.changeFile("A-file1.jpg"); // No 'down'! This version will become DIRTY
    clientA.createNewFile("dirty2");
    clientA.up(upOptionsForceEnabled);
   
    clientA.changeFile("A-file1.jpg"); // No 'down'! This version will become DIRTY
    clientA.createNewFile("dirty3");
    clientA.up(upOptionsForceEnabled);
   
    clientA.changeFile("A-file1.jpg"); // No 'down'! This version will become DIRTY
    clientA.createNewFile("dirty4");
    clientA.up(upOptionsForceEnabled);
   
    clientA.changeFile("A-file1.jpg"); // No 'down'! This version will become DIRTY
    clientA.createNewFile("dirty5");
    clientA.up(upOptionsForceEnabled);
   
    clientA.changeFile("A-file1.jpg"); // No 'down'! This version will become DIRTY
    clientA.createNewFile("dirty6");
    clientA.up(upOptionsForceEnabled);
   
    clientA.changeFile("A-file1.jpg"); // No 'down'! This version will become DIRTY
    clientA.createNewFile("dirty7");
    clientA.up(upOptionsForceEnabled);
   
    assertEquals("11", TestSqlUtil.runSqlSelect("select count(*) from databaseversion", databaseConnectionA));

    clientA.down();
    assertEquals("12", TestSqlUtil.runSqlSelect("select count(*) from databaseversion", databaseConnectionA));
    assertEquals("7", TestSqlUtil.runSqlSelect("select count(*) from databaseversion where status='DIRTY'", databaseConnectionA));
    assertEquals("5", TestSqlUtil.runSqlSelect("select count(*) from databaseversion where status<>'DIRTY'", databaseConnectionA));
    assertEquals("(A1)\n(A1,B1)\n(A2,B1)\n(A3,B1)\n(A3,B4)", TestSqlUtil.runSqlSelect("select vectorclock_serialized from databaseversion where status<>'DIRTY' order by id", databaseConnectionA));
   
    clientB.down(); // Does nothing; A versions lose against (A3,B2) // same as above!
    assertEquals("5", TestSqlUtil.runSqlSelect("select count(*) from databaseversion", databaseConnectionB));
    assertEquals("(A1)\n(A1,B1)\n(A2,B1)\n(A3,B1)\n(A3,B4)", TestSqlUtil.runSqlSelect("select vectorclock_serialized from databaseversion order by id", databaseConnectionB));
   

    //// 3. NEW CLIENT JOINS
   
    clientC.down();
    TestAssertUtil.assertSqlDatabaseEquals(clientB.getDatabaseFile(), clientC.getDatabaseFile());
   

    //// 4. FORCE MERGE DATABASES ON CLIENT A
   
    clientA.deleteFile("dirty1");
    clientA.deleteFile("dirty2");
   
    clientA.up(upOptionsForceEnabled); // upload DIRTY version
    assertEquals("6", TestSqlUtil.runSqlSelect("select count(*) from databaseversion", databaseConnectionA));
    assertEquals("0", TestSqlUtil.runSqlSelect("select count(*) from databaseversion where status='DIRTY'", databaseConnectionA));
    assertEquals("6", TestSqlUtil.runSqlSelect("select count(*) from databaseversion where status<>'DIRTY'", databaseConnectionA));
   
    clientA.createNewFile("A-file2.jpg");

    int numberOfDatabaseVersions = 6;
    int cleanupEveryXUps = 7; // For every X up's call 'cleanup' ("X" is larger than the max. length of file versions in a history)
   
    for (int i=1; i<=21; i++) {
      clientA.changeFile("A-file2.jpg");
     
      clientA.up(upOptionsForceEnabled);
      numberOfDatabaseVersions++;
         
      if (i % cleanupEveryXUps == 0) {
        clientA.cleanup(cleanupOptions);
        numberOfDatabaseVersions++;

        assertEquals(""+numberOfDatabaseVersions, TestSqlUtil.runSqlSelect("select count(*) from databaseversion where status<>'DIRTY'", databaseConnectionA));
      }
      else {
        assertEquals(""+numberOfDatabaseVersions, TestSqlUtil.runSqlSelect("select count(*) from databaseversion where status<>'DIRTY'", databaseConnectionA));
      }
    }
   
    clientA.cleanup(cleanupOptions);
   
    clientB.down();
    clientC.down();
    clientD.down();
   
    TestAssertUtil.assertSqlDatabaseEquals(clientA.getDatabaseFile(), clientB.getDatabaseFile());
    TestAssertUtil.assertSqlDatabaseEquals(clientA.getDatabaseFile(), clientC.getDatabaseFile());
    TestAssertUtil.assertSqlDatabaseEquals(clientA.getDatabaseFile(), clientD.getDatabaseFile());   
   
    // Tear down
    clientA.deleteTestData();
    clientB.deleteTestData();
    clientC.deleteTestData();
    clientD.deleteTestData();
  }
}
TOP

Related Classes of org.syncany.tests.scenarios.DirtyDatabaseScenarioTest

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.