package com.orgzly.android.repos; import android.net.Uri; import android.support.test.runner.AndroidJUnit4; import com.orgzly.BuildConfig; import com.orgzly.android.Book; import com.orgzly.android.BookName; import com.orgzly.android.Note; import com.orgzly.android.OrgzlyTest; import com.orgzly.android.prefs.AppPreferences; import com.orgzly.android.provider.clients.BooksClient; import com.orgzly.android.provider.clients.CurrentRooksClient; import com.orgzly.android.provider.clients.LocalDbRepoClient; import com.orgzly.android.provider.clients.ReposClient; import com.orgzly.android.sync.BookNamesake; import com.orgzly.android.sync.BookSyncStatus; import com.orgzly.android.util.EncodingDetect; import com.orgzly.android.util.MiscUtils; import com.orgzly.org.datetime.OrgRange; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.UUID; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; import static junit.framework.Assert.assertNotSame; import static junit.framework.Assert.assertNull; import static junit.framework.Assert.assertTrue; @RunWith(AndroidJUnit4.class) public class SyncTest extends OrgzlyTest { private static final String TAG = SyncTest.class.getName(); private Repo randomDirectoryRepo() { String uuid = UUID.randomUUID().toString(); return RepoFactory.getFromUri(context, "file:" + context.getCacheDir() + "/" + uuid); } @Before public void setUp() throws Exception { super.setUp(); AppPreferences.dropboxToken(context, BuildConfig.DROPBOX_TOKEN); } @Test public void testOrgRange() { shelfTestUtils.setupRepo("mock://repo-a"); shelfTestUtils.setupRook( "mock://repo-a", "mock://repo-a/remote-book-1.org", "* Note\nSCHEDULED: <2015-01-13 уто 13:00-14:14>--<2015-01-14 сре 14:10-15:20>", "0abcdef", 1400067156); shelf.sync(); Note note = shelf.getNote(2); /* ID 1 was a root from dummy which was deleted. */ OrgRange range = note.getHead().getScheduled(); assertEquals("<2015-01-13 уто 13:00-14:14>--<2015-01-14 сре 14:10-15:20>", range.toString()); } @Test public void testSync1() { shelfTestUtils.setupRepo("mock://repo-a"); shelfTestUtils.setupBook("todo", "hum hum"); assertEquals(1, ReposClient.getAll(context).size()); assertEquals(1, shelf.getBooks().size()); assertEquals(0, CurrentRooksClient.getAll(context).size()); assertNull(shelf.getBooks().get(0).getLastSyncedToRook()); shelf.sync(); assertEquals(1, ReposClient.getAll(context).size()); assertEquals(1, shelf.getBooks().size()); assertEquals(1, CurrentRooksClient.getAll(context).size()); assertNotNull(shelf.getBooks().get(0).getLastSyncedToRook()); assertEquals("mock://repo-a/todo.org", shelf.getBooks().get(0).getLastSyncedToRook().getUri().toString()); } @Test public void testSync2() { /* Add remote books. */ shelfTestUtils.setupRepo("mock://repo-a"); shelfTestUtils.setupRook("mock://repo-a", "mock://repo-a/remote-book-1.org", "", "1abcdef", 1400067156); shelfTestUtils.setupRook("mock://repo-a", "mock://repo-a/remote-book-2.org", "", "2abcdef", 1400067156); assertEquals(1, ReposClient.getAll(context).size()); assertEquals(2, LocalDbRepoClient.getAll(context, Uri.parse("mock://repo-a")).size()); assertEquals("mock://repo-a", LocalDbRepoClient.getAll(context, Uri.parse("mock://repo-a")).get(0).getRepoUri().toString()); assertEquals(0, CurrentRooksClient.getAll(context).size()); assertEquals(0, shelf.getBooks().size()); /* Sync. */ Map<String, BookNamesake> g1 = shelf.sync(); assertEquals(BookSyncStatus.DUMMY_WITHOUT_LINK_AND_ONE_ROOK, g1.get("remote-book-1").getStatus()); assertEquals(BookSyncStatus.DUMMY_WITHOUT_LINK_AND_ONE_ROOK, g1.get("remote-book-2").getStatus()); assertEquals(1, ReposClient.getAll(context).size()); assertEquals(2, LocalDbRepoClient.getAll(context, Uri.parse("mock://repo-a")).size()); assertEquals("mock://repo-a", LocalDbRepoClient.getAll(context, Uri.parse("mock://repo-a")).get(0).getRepoUri().toString()); assertEquals(2, CurrentRooksClient.getAll(context).size()); assertEquals(2, shelf.getBooks().size()); /* Sync. */ Map<String, BookNamesake> g2 = shelf.sync(); assertEquals(BookSyncStatus.NO_CHANGE, g2.get("remote-book-1").getStatus()); assertEquals(BookSyncStatus.NO_CHANGE, g2.get("remote-book-2").getStatus()); assertEquals(1, ReposClient.getAll(context).size()); assertEquals(2, LocalDbRepoClient.getAll(context, Uri.parse("mock://repo-a")).size()); assertEquals("mock://repo-a", LocalDbRepoClient.getAll(context, Uri.parse("mock://repo-a")).get(0).getRepoUri().toString()); assertEquals(2, CurrentRooksClient.getAll(context).size()); assertEquals(2, shelf.getBooks().size()); } @Test public void testRenameUsedRepo() { shelfTestUtils.setupRepo("mock://repo-a"); shelfTestUtils.setupRook("mock://repo-a", "mock://repo-a/book.org", "Content A", "1abcde", 1400067156000L); Book book; shelf.sync(); shelfTestUtils.renameRepo("mock://repo-a", "mock://repo-b"); book = shelf.getBook("book"); assertNull(book.getLink()); assertEquals("mock://repo-a/book.org", book.getLastSyncedToRook().getUri().toString()); assertEquals("mock://repo-a", book.getLastSyncedToRook().getRepoUri().toString()); shelf.sync(); book = shelf.getBook("book"); assertEquals(BookSyncStatus.ONLY_BOOK_WITHOUT_LINK_AND_ONE_REPO, book.getSyncStatus()); assertEquals("mock://repo-b/book.org", book.getLastSyncedToRook().getUri().toString()); assertEquals("mock://repo-b", book.getLastSyncedToRook().getRepoUri().toString()); assertEquals("mock://repo-b/book.org", book.getLink().getUri().toString()); assertEquals("mock://repo-b", book.getLink().getRepoUri().toString()); shelfTestUtils.renameRepo("mock://repo-b", "mock://repo-a"); shelf.sync(); book = shelf.getBook("book"); assertEquals(BookSyncStatus.BOOK_WITHOUT_LINK_AND_ONE_OR_MORE_ROOKS_EXIST, book.getSyncStatus()); assertNull(book.getLink()); assertEquals("mock://repo-b/book.org", book.getLastSyncedToRook().getUri().toString()); assertEquals("mock://repo-b", book.getLastSyncedToRook().getRepoUri().toString()); } @Test public void testDeletingUsedRepo() { Book book; shelfTestUtils.setupRepo("mock://repo-a"); shelfTestUtils.setupRook("mock://repo-a", "mock://repo-a/book.org", "Content A", "1abcde", 1400067156000L); shelf.sync(); shelfTestUtils.deleteRepo("mock://repo-a"); shelfTestUtils.setupRepo("mock://repo-b"); shelf.sync(); book = shelf.getBook("book"); assertEquals(BookSyncStatus.ONLY_BOOK_WITHOUT_LINK_AND_ONE_REPO, book.getSyncStatus()); assertEquals("mock://repo-b/book.org", book.getLink().getUri().toString()); assertEquals("mock://repo-b", book.getLink().getRepoUri().toString()); assertEquals("mock://repo-b/book.org", book.getLastSyncedToRook().getUri().toString()); shelfTestUtils.deleteRepo("mock://repo-b"); shelfTestUtils.setupRepo("mock://repo-a"); shelf.sync(); book = shelf.getBook("book"); assertEquals(BookSyncStatus.BOOK_WITHOUT_LINK_AND_ONE_OR_MORE_ROOKS_EXIST, book.getSyncStatus()); assertNull(book.getLink()); assertEquals("mock://repo-b/book.org", book.getLastSyncedToRook().getUri().toString()); } @Test public void testEncodingStaysTheSameAfterSecondSync() { Book book; shelfTestUtils.setupRepo("mock://repo-a"); shelfTestUtils.setupRook("mock://repo-a", "mock://repo-a/book.org", "Content A", "1abcde", 1400067156000L); shelf.sync(); book = shelf.getBooks().get(0); assertEquals(BookSyncStatus.DUMMY_WITHOUT_LINK_AND_ONE_ROOK, book.getSyncStatus()); switch (EncodingDetect.USED_METHOD) { // case JCHARDET: // assertEquals("ASCII", versionedRook.getDetectedEncoding()); // assertEquals("ASCII", versionedRook.getUsedEncoding()); case JUNIVERSALCHARDET: assertNull(book.getDetectedEncoding()); assertEquals("UTF-8", book.getUsedEncoding()); break; } assertNull(book.getSelectedEncoding()); shelf.sync(); book = shelf.getBooks().get(0); assertEquals(BookSyncStatus.NO_CHANGE, book.getSyncStatus()); switch (EncodingDetect.USED_METHOD) { // case JCHARDET: // assertEquals("ASCII", versionedRook.getDetectedEncoding()); // assertEquals("ASCII", versionedRook.getUsedEncoding()); // break; case JUNIVERSALCHARDET: assertNull(book.getDetectedEncoding()); assertEquals("UTF-8", book.getUsedEncoding()); break; } assertNull(book.getSelectedEncoding()); } @Test public void testOnlyBookWithLink() { shelfTestUtils.setupRepo("mock://repo-a"); shelfTestUtils.setupBook("book-1", "Content"); shelfTestUtils.setBookLink(1, "mock://repo-a", "mock://repo-a/book-1.org"); shelf.sync(); Book book = shelf.getBooks().get(0); assertEquals(BookSyncStatus.ONLY_BOOK_WITH_LINK, book.getSyncStatus()); } @Test public void testMultipleRooks() { shelfTestUtils.setupRepo("mock://repo-a"); shelfTestUtils.setupRook("mock://repo-a", "mock://repo-a/book.org", "Content A", "revA", 1234567890000L); shelfTestUtils.setupRepo("mock://repo-b"); shelfTestUtils.setupRook("mock://repo-b", "mock://repo-b/book.org", "Content B", "revB", 1234567890000L); shelf.sync(); Book book = shelf.getBooks().get(0); assertEquals(BookSyncStatus.DUMMY_WITHOUT_LINK_AND_MULTIPLE_ROOKS, book.getSyncStatus()); assertTrue(book.isDummy()); shelfTestUtils.setBookLink(book.getId(), "mock://repo-a", "mock://repo-a/book.org"); shelf.sync(); book = shelf.getBooks().get(0); assertEquals(BookSyncStatus.DUMMY_WITH_LINK, book.getSyncStatus()); assertTrue(!book.isDummy()); assertEquals("mock://repo-a/book.org", book.getLastSyncedToRook().getUri().toString()); } @Test public void testMtimeOfLoadedBook() { shelfTestUtils.setupRepo("mock://repo-a"); shelfTestUtils.setupRook("mock://repo-a", "mock://repo-a/book.org", "Content", "rev", 1234567890000L); shelf.sync(); Book book = shelf.getBooks().get(0); assertEquals(BookSyncStatus.DUMMY_WITHOUT_LINK_AND_ONE_ROOK, book.getSyncStatus()); assertEquals(0, book.getMtime()); } @Test public void testDummyShouldNotBeSavedWhenHavingOneRepo() { shelfTestUtils.setupRepo("mock://repo-a"); shelfTestUtils.setupRepo("mock://repo-b"); shelfTestUtils.setupRook("mock://repo-a", "mock://repo-a/booky.org", "", "1abcdef", 1400067155); shelfTestUtils.setupRook("mock://repo-b", "mock://repo-b/booky.org", "", "2abcdef", 1400067156); Book book; Map<String, BookNamesake> namesakes; namesakes = shelf.sync(); book = shelf.getBook("booky"); assertEquals(BookSyncStatus.DUMMY_WITHOUT_LINK_AND_MULTIPLE_ROOKS, namesakes.get("booky").getStatus()); assertTrue(book.isDummy()); shelfTestUtils.deleteRepo("mock://repo-a"); shelfTestUtils.deleteRepo("mock://repo-b"); shelfTestUtils.setupRepo("mock://repo-c"); namesakes = shelf.sync(); book = shelf.getBook("booky"); assertEquals(BookSyncStatus.ONLY_DUMMY, namesakes.get("booky").getStatus()); // TODO: We should delete it, no point of having a dummy and no remote book assertTrue(book.isDummy()); } @Test public void testDeletedRepoShouldStayAsBookLink() { shelfTestUtils.setupRepo("mock://repo-a"); shelfTestUtils.setupRepo("mock://repo-b"); shelfTestUtils.setupRook("mock://repo-a", "mock://repo-a/booky.org", "", "1abcdef", 1400067155); Book book; Map<String, BookNamesake> namesakes; namesakes = shelf.sync(); book = shelf.getBook("booky"); assertEquals(BookSyncStatus.DUMMY_WITHOUT_LINK_AND_ONE_ROOK, namesakes.get("booky").getStatus()); assertFalse(book.isDummy()); assertEquals("mock://repo-a", book.getLink().getRepoUri().toString()); assertEquals("mock://repo-a", book.getLastSyncedToRook().getRepoUri().toString()); shelfTestUtils.deleteRepo("mock://repo-a"); shelfTestUtils.deleteRepo("mock://repo-b"); shelfTestUtils.setupRepo("mock://repo-c"); namesakes = shelf.sync(); // TODO: Don't use namesakes, be consistent and use book.status like in some methods book = shelf.getBook("booky"); assertEquals(BookSyncStatus.ONLY_BOOK_WITHOUT_LINK_AND_ONE_REPO, namesakes.get("booky").getStatus()); assertFalse(book.isDummy()); assertEquals("mock://repo-c", book.getLink().getRepoUri().toString()); assertEquals("mock://repo-c", book.getLastSyncedToRook().getRepoUri().toString()); } // public void testEncodingOnSyncSavingStaysTheSame() { // setup.setupRepo("mock://repo-a"); // setup.setupRook("mock://repo-a", "mock://repo-a/book.org", "Content A", "1abcde", 1400067156000L); // sync(); // setup.renameRepo("mock://repo-a", "mock://repo-b"); // sync(); // VersionedRook vrook = CurrentRooksHelper.get(testContext, "mock://repo-b/book.org"); // assertNull(vrook.getDetectedEncoding()); // assertEquals("UTF-8", vrook.getUsedEncoding()); // // } @Test public void testSyncingOrgTxt() { shelfTestUtils.setupRepo("mock://repo-a"); shelfTestUtils.setupRook("mock://repo-a", "mock://repo-a/booky.org.txt", "", "1abcdef", 1400067155); shelf.sync(); Book book = shelf.getBook("booky"); assertEquals("mock://repo-a", book.getLink().getRepoUri().toString()); assertEquals("mock://repo-a/booky.org.txt", book.getLink().getUri().toString()); assertEquals("mock://repo-a", book.getLastSyncedToRook().getRepoUri().toString()); assertEquals("mock://repo-a/booky.org.txt", book.getLastSyncedToRook().getUri().toString()); } @Test public void testMockFileRename() throws IOException { List<VersionedRook> vrooks; Repo repo = shelfTestUtils.setupRepo("mock://repo-a"); Book book = shelfTestUtils.setupBook("Booky", "1 2 3"); shelf.sync(); vrooks = repo.getBooks(); assertEquals(1, vrooks.size()); assertEquals("Booky", BookName.getInstance(context, vrooks.get(0)).getName()); long mtime = vrooks.get(0).getMtime(); String rev = vrooks.get(0).getRevision(); // Rename local notebook shelf.renameBook(book, "BookyRenamed"); // Rename rook repo.renameBook(Uri.parse("mock://repo-a/Booky.org"), "BookyRenamed"); vrooks = repo.getBooks(); assertEquals(1, vrooks.size()); assertEquals("BookyRenamed", BookName.getInstance(context, vrooks.get(0)).getName()); assertEquals("mock://repo-a/BookyRenamed.org", vrooks.get(0).getUri().toString()); assertTrue(mtime < vrooks.get(0).getMtime()); assertNotSame(rev, vrooks.get(0).getRevision()); } @Test public void testDropboxFileRename() throws IOException { Repo repo = DropboxRepoTest.randomDropboxRepo(context); assertNotNull(repo); assertEquals(0, repo.getBooks().size()); File file = File.createTempFile("notebook.", ".org"); MiscUtils.writeStringToFile("1 2 3", file); VersionedRook vrook = repo.storeBook(file, file.getName()); assertEquals(1, repo.getBooks().size()); repo.renameBook(vrook.getUri(), "notebook-renamed"); assertEquals(1, repo.getBooks().size()); assertEquals(repo.getUri() + "/notebook-renamed.org", repo.getBooks().get(0).getUri().toString()); assertEquals("notebook-renamed.org", BookName.getInstance(context, repo.getBooks().get(0)).getFileName()); } @Test public void testDirectoryFileRename() throws IOException { Repo repo = randomDirectoryRepo(); assertNotNull(repo); assertEquals(0, repo.getBooks().size()); File file = File.createTempFile("notebook.", ".org"); MiscUtils.writeStringToFile("1 2 3", file); VersionedRook vrook = repo.storeBook(file, file.getName()); assertEquals(1, repo.getBooks().size()); repo.renameBook(vrook.getUri(), "notebook-renamed"); assertEquals(1, repo.getBooks().size()); assertEquals(repo.getUri() + "/notebook-renamed.org", repo.getBooks().get(0).getUri().toString()); assertEquals("notebook-renamed.org", BookName.getInstance(context, repo.getBooks().get(0)).getFileName()); } @Test public void testRenameSyncedBook() throws IOException { shelfTestUtils.setupRepo("mock://repo-a"); shelfTestUtils.setupBook("Booky", "1 2 3"); shelf.sync(); Book book = BooksClient.get(context, "Booky"); assertEquals("mock://repo-a/Booky.org", book.getLastSyncedToRook().getUri().toString()); shelf.renameBook(book, "BookyRenamed"); Book renamedBook = BooksClient.get(context, "BookyRenamed"); assertEquals("mock://repo-a/BookyRenamed.org", renamedBook.getLink().getUri().toString()); assertEquals("mock://repo-a/BookyRenamed.org", renamedBook.getLastSyncedToRook().getUri().toString()); } @Test public void testRenameSyncedBookWithDifferentLink() throws IOException { Book book; Repo repoA = shelfTestUtils.setupRepo("mock://repo-a"); Repo repoB = shelfTestUtils.setupRepo("mock://repo-b"); book = shelfTestUtils.setupBook("Booky", "1 2 3"); shelf.setLink(book, "mock://repo-a"); shelf.sync(); book = BooksClient.getAll(context).get(0); assertEquals(1, repoA.getBooks().size()); assertEquals(0, repoB.getBooks().size()); assertEquals("mock://repo-a/Booky.org", book.getLink().getUri().toString()); assertEquals("mock://repo-a/Booky.org", book.getLastSyncedToRook().getUri().toString()); shelf.setLink(book, "mock://repo-b"); book = BooksClient.getAll(context).get(0); shelf.renameBook(book, "BookyRenamed"); book = BooksClient.getAll(context).get(0); assertEquals("Booky", book.getName()); assertEquals(BookSyncStatus.ROOK_AND_VROOK_HAVE_DIFFERENT_REPOS, book.getSyncStatus()); assertEquals("mock://repo-b/Booky.org", book.getLink().getUri().toString()); assertEquals("mock://repo-a/Booky.org", book.getLastSyncedToRook().getUri().toString()); } }