package com.orgzly.android.misc; import android.util.Log; import com.orgzly.android.Book; import com.orgzly.android.BookName; import com.orgzly.android.LipsumBookGenerator; import com.orgzly.android.OrgzlyTest; import com.orgzly.android.util.MiscUtils; import org.junit.Test; import java.io.File; import java.io.IOException; import java.io.InputStream; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.fail; public class BookParsingTest extends OrgzlyTest { private static final String TAG = BookParsingTest.class.getName(); private boolean runResourcesDemandingTest() { if (true) return false; Log.d(TAG, "Deciding whether to run test for" + " MODEL:" + android.os.Build.MODEL + " FINGERPRINT:" + android.os.Build.FINGERPRINT + " BRAND:" + android.os.Build.BRAND + " DEVICE:" + android.os.Build.DEVICE + " HARDWARE:" + android.os.Build.HARDWARE ); switch (android.os.Build.MODEL) { /* Do not run test for these. */ case "Full Android on x86 Emulator": case "Android SDK built for x86_64": case "GT-I5500": case "GT-I9300": case "HTC One V": return false; } return true; } @Test public void testBookContent1() throws IOException { onBook("Sample book used for tests\n\n\n* Note") .onLoad() .isContent("Sample book used for tests") .isNoteTitle(1, "Note") .isNoteLevel(1, 1) .isWhenSaved("Sample book used for tests\n\n* Note\n"); } @Test public void testBookContentPrefixedWithSpaces() { onBook(" Sample book used for tests\n\n\n* Note") .onLoad() .isContent(" Sample book used for tests") .isNoteTitle(1, "Note") .isNoteLevel(1, 1) .isWhenSaved(" Sample book used for tests\n\n* Note\n"); } @Test public void testBookContent2() throws IOException { onBook("\nSample book used for tests\n\n\n* Note") .onLoad() .isContent("Sample book used for tests") .isNoteTitle(1, "Note") .isNoteLevel(1, 1) .isWhenSaved("Sample book used for tests\n\n* Note\n"); } @Test public void testSavingWithPriorities() throws IOException { onBook("\nSample book used for tests\n\n\n* Note 1\n* [#B] Note 2\n* [#A] Note 3") .onLoad() .isContent("Sample book used for tests") .isWhenSaved("Sample book used for tests\n\n* Note 1\n* [#B] Note 2\n* [#A] Note 3\n"); } @Test public void testNotIndented1() throws IOException { onBook("* Note 1\nSCHEDULED: <2015-02-11 Wed +1d>").onLoad() .isWhenSaved("* Note 1\nSCHEDULED: <2015-02-11 Wed +1d>\n\n"); } @Test public void testNotIndented2() throws IOException { onBook("* Note 1\n:LOGBOOK:\n:END:").onLoad() .isWhenSaved("* Note 1\n:LOGBOOK:\n:END:\n\n"); } @Test public void testIndented1() throws IOException { onBook("* Note 1\n SCHEDULED: <2015-02-11 Wed +1d>").onLoad() .isWhenSaved("* Note 1\n SCHEDULED: <2015-02-11 Wed +1d>\n\n"); } @Test public void testIndented2() throws IOException { onBook("* Note 1\n :LOGBOOK:\n :END:").onLoad() .isWhenSaved("* Note 1\n :LOGBOOK:\n :END:\n\n"); } @Test public void testEmptyProperties() throws IOException { onBook("* Note 1\n :PROPERTIES:\n :END:").onLoad() .isWhenSaved("* Note 1\n"); } @Test public void testProperties() throws IOException { onBook("* Note 1\n" + " :PROPERTIES:\n" + " :name: value\n" + " :END:").onLoad() .isWhenSaved("* Note 1\n" + " :PROPERTIES:\n" + " :name: value\n" + " :END:\n\n"); } @Test public void testPropertiesMultiple() throws IOException { onBook("* Note 1\n" + " :PROPERTIES:\n" + " :name2: value2\n" + " :name1: value1\n" + " :END:").onLoad() .isWhenSaved("* Note 1\n" + " :PROPERTIES:\n" + " :name2: value2\n" + " :name1: value1\n" + " :END:\n\n"); } @Test public void testPropertiesEmpty() throws IOException { onBook("* Note 1\n" + " :PROPERTIES:\n" + " :END:").onLoad() .isWhenSaved("* Note 1\n"); } @Test public void testParsingClockTimesOutsideLogbook() { onBook("* STARTED Test times\n" + " CLOCK: [2016-10-27 Thu 18:40]--[2016-10-27 Thu 18:51] => 0:11\n" + " CLOCK: [2016-10-27 Thu 18:10]--[2016-10-27 Thu 18:25] => 0:15\n" + " CLOCK: [2016-10-27 Thu 17:50]--[2016-10-27 Thu 18:05] => 0:15\n") .onLoad() .isWhenSaved("* STARTED Test times\n" + " CLOCK: [2016-10-27 Thu 18:40]--[2016-10-27 Thu 18:51] => 0:11\n" + " CLOCK: [2016-10-27 Thu 18:10]--[2016-10-27 Thu 18:25] => 0:15\n" + " CLOCK: [2016-10-27 Thu 17:50]--[2016-10-27 Thu 18:05] => 0:15\n\n"); } /* * Books in different languages, different sizes and formats ... */ @Test public void testLoadingTextDv() throws IOException { onBookFile("html/dv.org").onLoad().onGet(); } @Test public void testLoadingTextZh() throws IOException { onBookFile("html/zh.org").onLoad().onGet(); } @Test public void testLoadingHuge() throws IOException { if (runResourcesDemandingTest()) { onBookFile("org/org-issues.10x.org").onLoad(); } } /* * Files generated using http://generator.lorem-ipsum.info/ ... */ @Test public void testLoadingArabicLipsum() throws IOException { onBookFile("lipsum/Arabic-Lipsum.org").onLoad().onGet(); } @Test public void testLoadingChineseLipsum() throws IOException { onBookFile("lipsum/Chinese-Lipsum.org").onLoad().onGet(); } @Test public void testLoadingGreekLipsum() throws IOException { onBookFile("lipsum/Greek-Lipsum.org").onLoad().onGet(); } @Test public void testLoadingHebrewLipsum() throws IOException { onBookFile("lipsum/Hebrew-Lipsum.org").onLoad().onGet(); } @Test public void testLoadingHindiLipsum() throws IOException { onBookFile("lipsum/Hindi-Lipsum.org").onLoad().onGet(); } @Test public void testLoadingJapaneseLipsum() throws IOException { onBookFile("lipsum/Japanese-Lipsum.org").onLoad().onGet(); } @Test public void testLoadingL33TspeakLipsum() throws IOException { onBookFile("lipsum/L33tspeak-Lipsum.org").onLoad().onGet(); } @Test public void testLoadingRussianLipsum() throws IOException { onBookFile("lipsum/Russian-Lipsum.org").onLoad().onGet(); } /* * Loading images as books ... */ // @Test // public void testLoadingLargerJpg() { // if (runResourcesDemandingTest()) { // onBookFile("images/IMG_2932.org").onLoadFailed(); // } // } @Test public void testLoadingSmallPng() { onBookFile("images/logo11w.org").onLoad(); } @Test public void testLion() { if (runResourcesDemandingTest()) { onBookFile("images/lion-wide.org").onLoad(); } } /* * Generated lipsum ... */ @Test public void testLoadingLatinLipsumHugeBookContentWithTitleTitleAndNoteContent() { if (runResourcesDemandingTest()) { String data = LipsumBookGenerator.generateOrgString(1000000, new int[] { 1000000, 1000000 }); onBook(data).onLoadFailed(); } } @Test public void testLoadingLatinLipsumHugeNoteTitle() { if (runResourcesDemandingTest()) { String data = LipsumBookGenerator.generateOrgString(0, new int[] { 2000000, 0 }); onBook(data).onLoadFailed(); } } @Test public void testLoadingLatinLipsumLargeNoteTitles() { if (runResourcesDemandingTest()) { String data = LipsumBookGenerator.generateOrgString(0, new int[] { 1000000, 0, 1500000, 1 }); onBook(data).onLoad(); } } @Test public void testLoadingLatinLipsumHugeNoteTitleWithContent() { if (runResourcesDemandingTest()) { String data = LipsumBookGenerator.generateOrgString(0, new int[] { 1000000, 1000000 }); onBook(data).onLoadFailed(); } } @Test public void testBookContentTooBig() { if (runResourcesDemandingTest()) { String data = LipsumBookGenerator.generateOrgString(2000000, null); onBook(data).onLoadFailed(); } } public TestedBook onBookFile(String resourceName) { return new TestedBook(new TestedBookSourceFromResource(resourceName)); } public TestedBook onBook(String content) { return new TestedBook(new TestedBookSourceFromContent(content)); } class TestedBook { private final TestedBookSource bookSource; private Book book; public TestedBook(TestedBookSource bookSource) { this.bookSource = bookSource; } public TestedBook onLoad() { shelf.clearDatabase(); File tmpFile = bookSource.getTmpFile(); try { /* Load from file. */ shelf.loadBookFromFile("Notebook", BookName.Format.ORG, tmpFile); } catch (IOException e) { e.printStackTrace(); fail(e.toString()); } finally { tmpFile.delete(); } book = shelf.getBooks().get(0); return this; } public TestedBook onGet() { try { book = shelf.getBooks().get(0); } catch (Exception e) { e.printStackTrace(); fail(e.toString()); } return this; } public TestedBook onGetFailed() { try { book = shelf.getBooks().get(0); fail("Book should fail to load"); } catch (Exception e) { e.printStackTrace(); } return this; } public TestedBook onLoadFailed() { shelf.clearDatabase(); File tmpFile = bookSource.getTmpFile(); try { /* Load from file. */ shelf.loadBookFromFile("Notebook", BookName.Format.ORG, tmpFile); fail("Book should fail to load"); } catch (IOException e) { e.printStackTrace(); } finally { tmpFile.delete(); } return this; } public TestedBook isContent(String str) { if (book == null) fail("Notebook not loaded. Call onLoad()."); Book book = shelf.getBooks().get(0); assertEquals("Content", str, book.getPreface()); return this; } public TestedBook isNoteTitle(int note, String str) { if (book == null) fail("Notebook not loaded. Call onLoad()"); assertEquals("Title", str, shelf.getNote(note).getHead().getTitle()); return this; } public TestedBook isNoteLevel(int note, int level) { if (book == null) fail("Notebook not loaded. Call onLoad()"); assertEquals("Note level", level, shelf.getNote(note).getPosition().getLevel()); return this; } public TestedBook isWhenSaved(String expacted) { if (book == null) fail("Notebook not loaded. Call onLoad()"); try { /* Write from db -> temp file. */ File file = shelf.getTempBookFile(); try { shelf.writeBookToFile(book, BookName.Format.ORG, file); assertEquals("Notebook", expacted, MiscUtils.readStringFromFile(file)); } finally { file.delete(); } } catch (IOException e) { e.printStackTrace(); fail(e.toString()); } return this; } } private interface TestedBookSource { File getTmpFile(); } private class TestedBookSourceFromContent implements TestedBookSource { private String content; public TestedBookSourceFromContent(String content) { this.content = content; } @Override public File getTmpFile() { File file = null; try { file = shelf.getTempBookFile(); MiscUtils.writeStringToFile(content, file); } catch (IOException e) { e.printStackTrace(); fail(e.toString()); } return file; } } private class TestedBookSourceFromResource implements TestedBookSource { private String resourceName; public TestedBookSourceFromResource(String resourceName) { this.resourceName = resourceName; } @Override public File getTmpFile() { InputStream stream = BookParsingTest.class.getClassLoader().getResourceAsStream("assets/" + resourceName); if (stream == null) { fail("Resource " + resourceName + " not found inside assets/"); } File file = null; try { file = shelf.getTempBookFile(); MiscUtils.writeStreamToFile(stream, file); stream.close(); } catch (IOException e) { e.printStackTrace(); fail(e.toString()); } return file; } } }