diff --git a/lib/src/main/cpp/libkiwix/book.cpp b/lib/src/main/cpp/libkiwix/book.cpp index 81ec03b..9470e02 100644 --- a/lib/src/main/cpp/libkiwix/book.cpp +++ b/lib/src/main/cpp/libkiwix/book.cpp @@ -93,7 +93,7 @@ METHOD0(jobjectArray, getIllustrations) { jobjectArray retArray = createArray(env, illustrations.size(), "org/kiwix/libkiwix/Illustration"); size_t index = 0; for (auto illu: illustrations) { - auto wrapper = BUILD_WRAPPER("org/kiwix/libkiwx/Illustration", illu); + auto wrapper = BUILD_WRAPPER("org/kiwix/libkiwix/Illustration", illu); env->SetObjectArrayElement(retArray, index++, wrapper); } return retArray; diff --git a/lib/src/main/cpp/libzim/archive.cpp b/lib/src/main/cpp/libzim/archive.cpp index 3392977..870d535 100644 --- a/lib/src/main/cpp/libzim/archive.cpp +++ b/lib/src/main/cpp/libzim/archive.cpp @@ -164,7 +164,7 @@ METHOD(jobject, getEntryByTitle__I, jint index) { } METHOD(jboolean, hasEntryByTitle, jstring title) { - return TO_JNI(THIS->hasEntryByPath(TO_C(title))); + return TO_JNI(THIS->hasEntryByTitle(TO_C(title))); } METHOD(jobject, getEntryByClusterOrder, jint index) { diff --git a/lib/src/main/cpp/libzim/entry_iterator.cpp b/lib/src/main/cpp/libzim/entry_iterator.cpp index 9f19d56..78aa840 100644 --- a/lib/src/main/cpp/libzim/entry_iterator.cpp +++ b/lib/src/main/cpp/libzim/entry_iterator.cpp @@ -66,22 +66,19 @@ METHOD0(void, dispose) METHOD0(jboolean, hasNext) { switch (get_order(env, thisObj)) { case 0: { - PATH_NATIVE_TYPE next(*GET_PTR(PATH_NATIVE_TYPE)); - next++; + PATH_NATIVE_TYPE current(*GET_PTR(PATH_NATIVE_TYPE)); auto end = getPtr(env, thisObj, "nativeHandleEnd"); - return next == *end; + return current != *end; } case 1: { - TITLE_NATIVE_TYPE next(*GET_PTR(TITLE_NATIVE_TYPE)); - next++; + TITLE_NATIVE_TYPE current(*GET_PTR(TITLE_NATIVE_TYPE)); auto end = getPtr(env, thisObj, "nativeHandleEnd"); - return next == *end; + return current != *end; } case 2: { - EFFICIENT_NATIVE_TYPE next(*GET_PTR(EFFICIENT_NATIVE_TYPE)); - next++; + EFFICIENT_NATIVE_TYPE current(*GET_PTR(EFFICIENT_NATIVE_TYPE)); auto end = getPtr(env, thisObj, "nativeHandleEnd"); - return next == *end; + return current != *end; } default: // unreachable!() @@ -92,18 +89,18 @@ METHOD0(jboolean, hasNext) { METHOD0(jobject, next) { switch (get_order(env, thisObj)) { case 0: { - (*GET_PTR(PATH_NATIVE_TYPE))++; zim::Entry entry = **GET_PTR(PATH_NATIVE_TYPE); + (*GET_PTR(PATH_NATIVE_TYPE))++; return BUILD_WRAPPER("org/kiwix/libzim/Entry", entry); } case 1: { - (*GET_PTR(TITLE_NATIVE_TYPE))++; zim::Entry entry = **GET_PTR(TITLE_NATIVE_TYPE); + (*GET_PTR(TITLE_NATIVE_TYPE))++; return BUILD_WRAPPER("org/kiwix/libzim/Entry", entry); } case 2: { - (*GET_PTR(EFFICIENT_NATIVE_TYPE))++; zim::Entry entry = **GET_PTR(EFFICIENT_NATIVE_TYPE); + (*GET_PTR(EFFICIENT_NATIVE_TYPE))++; return BUILD_WRAPPER("org/kiwix/libzim/Entry", entry); } default: diff --git a/lib/src/main/cpp/libzim/search_iterator.cpp b/lib/src/main/cpp/libzim/search_iterator.cpp index 65e1342..c449406 100644 --- a/lib/src/main/cpp/libzim/search_iterator.cpp +++ b/lib/src/main/cpp/libzim/search_iterator.cpp @@ -57,10 +57,8 @@ METHOD0(jstring, getZimId) { } METHOD0(jboolean, hasNext) { - zim::SearchIterator next(*THIS); - next++; auto end = getPtr(env, thisObj, "nativeHandleEnd"); - return next == *end; + return *THIS != *end; } METHOD0(jobject, next) { diff --git a/lib/src/test/catalog.xml b/lib/src/test/catalog.xml index 3e2f6ac..e0724b5 100644 --- a/lib/src/test/catalog.xml +++ b/lib/src/test/catalog.xml @@ -2,17 +2,24 @@ 00000000-0000-0000-0000-000000000000 Test ZIM file - urn:uuid:86c91e51-55bf-8882-464e-072aca37a3e8 + urn:uuid:e34f5109-ed0d-b93e-943d-06f7717c7340 /meta?name=favicon&content=small 2020-11-27:00::00:Z - en - This is a ZIM file used in libzim unit-tests - unit;test + small.zim + eng + Description + _category:Category;_ftindex:yes;_ftindex:yes;_pictures:yes;_videos:yes;_details:yes - Kiwix + Creator - + + Publisher + + Category + 1 + 1 + diff --git a/lib/src/test/create_test_zimfiles b/lib/src/test/create_test_zimfiles index ac60bcd..43bbf66 100755 --- a/lib/src/test/create_test_zimfiles +++ b/lib/src/test/create_test_zimfiles @@ -13,10 +13,11 @@ zimwriterfs -w main.html \ -I favicon.png \ -l eng \ -t "Test ZIM file" \ - -d "N/A" \ - -L "Test File" \ - -c "N/A" \ - -p "N/A" \ + -d "Description" \ + -L "Long Description" \ + -c "Creator" \ + -p "Publisher" \ + --tags "_category:Category" \ small_zimfile_data \ small.zim \ && echo 'small.zim was successfully created' \ diff --git a/lib/src/test/library.xml b/lib/src/test/library.xml new file mode 100644 index 0000000..f0fc637 --- /dev/null +++ b/lib/src/test/library.xml @@ -0,0 +1,3 @@ + + + diff --git a/lib/src/test/small.zim b/lib/src/test/small.zim index eb9674b..efcf89c 100644 Binary files a/lib/src/test/small.zim and b/lib/src/test/small.zim differ diff --git a/lib/src/test/small.zim.embedded b/lib/src/test/small.zim.embedded index 95c84b0..fe7248b 100644 Binary files a/lib/src/test/small.zim.embedded and b/lib/src/test/small.zim.embedded differ diff --git a/lib/src/test/test.java b/lib/src/test/test.java index 7d4b25e..db50102 100644 --- a/lib/src/test/test.java +++ b/lib/src/test/test.java @@ -50,31 +50,109 @@ public class test { throws IOException { // test the zim file main page title TestEntry mainPage = archive.getMainEntry(); + assertTrue(mainPage.isRedirect()); assertEquals("mainPage", mainPage.getTitle()); assertEquals("Test ZIM file", mainPage.getItem(true).getTitle()); + assertEquals("Test ZIM file", mainPage.getRedirectEntry().getTitle()); + assertEquals("Test ZIM file", mainPage.getRedirect().getTitle()); // test zim file main url assertEquals("mainPage", mainPage.getPath()); assertEquals("main.html", mainPage.getItem(true).getPath()); // test zim file size - assertEquals(66910, archive.getFilesize()); // The file size is in KiB + assertEquals(66937, archive.getFilesize()); // The file size is in KiB // test zim file content byte[] mainData = getFileContent("small_zimfile_data/main.html"); byte[] inZimMainData = archive.getEntryByPath("main.html").getItem(true).getData().getData(); - assert(Arrays.equals(mainData, inZimMainData)); + assertTrue(Arrays.equals(mainData, inZimMainData)); // test zim file icon - assertEquals(true, archive.hasIllustration(48)); + assertTrue(archive.hasIllustration(48)); byte[] faviconData = getFileContent("small_zimfile_data/favicon.png"); TestItem item = archive.getIllustrationItem(48); assertEquals(faviconData.length, item.getSize()); - assert(Arrays.equals(faviconData, item.getData().getData())); + assertEquals("image/png", item.getMimetype()); + TestBlob illustrationData = item.getData(); + assertEquals(faviconData.length, illustrationData.size()); + assertTrue(Arrays.equals(faviconData, illustrationData.getData())); // Checking direct access information DirectAccessInfo dai = item.getDirectAccessInformation(); assertNotEquals("", dai.filename); byte[] readData = getFileContentPartial(dai.filename, (int) dai.offset, (int) item.getSize()); - assert(Arrays.equals(faviconData, readData)); + assertTrue(Arrays.equals(faviconData, readData)); + + // Checking all metadata + assertFalse(archive.isMultiPart()); + assertTrue(archive.hasNewNamespaceScheme()); + assertTrue(archive.hasChecksum()); + assertEquals("4a2709fddbee8c27db708c20b4952a06", archive.getChecksum()); + assertTrue(archive.hasTitleIndex()); + assertTrue(archive.hasFulltextIndex()); + assertTrue(archive.hasMainEntry()); + long[] illuSizes = {48}; + assertTrue(Arrays.equals(illuSizes, archive.getIllustrationSizes())); + String[] metaKeys = {"Counter", "Creator", "Date", "Description", "Illustration_48x48@1", "Language", "LongDescription", "Name", "Publisher", "Scraper", "Tags", "Title"}; + assertTrue(Arrays.equals( + metaKeys, + archive.getMetadataKeys() + )); + assertEquals("e34f5109-ed0d-b93e-943d-06f7717c7340", archive.getUuid()); + assertEquals(1, archive.getMediaCount()); + assertEquals(1, archive.getArticleCount()); + assertEquals(2, archive.getEntryCount()); + assertEquals(19, archive.getAllEntryCount()); + assertTrue(archive.hasEntryByTitle("Test ZIM file")); + assertTrue(archive.hasEntryByPath("main.html")); + assertEquals("Test ZIM file", archive.getEntryByTitle("Test ZIM file").getTitle()); + assertEquals("main.html", archive.getEntryByPath("main.html").getPath()); + assertEquals("Test ZIM file", archive.getEntryByTitle(0).getTitle()); + assertEquals("main.html", archive.getEntryByPath(1).getPath()); + assertEquals("main.html", archive.getEntryByClusterOrder(0).getPath()); + + + assertEquals("Test ZIM file", archive.getMetadata("Title")); + assertEquals("Title", archive.getMetadataItem("Title").getTitle()); + + assertFalse(archive.getRandomEntry().getTitle().isEmpty()); + + { + TestEntryIterator iter = archive.iterByPath(); + assertTrue(iter.hasNext()); + assertEquals("favicon.png", iter.next().getPath()); + assertEquals("main.html", iter.next().getPath()); + assertFalse(iter.hasNext()); + } + + { + TestEntryIterator iter = archive.iterByTitle(); + assertTrue(iter.hasNext()); + assertEquals("main.html", iter.next().getPath()); + // No favicon, because favicon is not a main article (no title) + assertFalse(iter.hasNext()); + } + + { + TestEntryIterator iter = archive.iterEfficient(); + assertTrue(iter.hasNext()); + assertEquals("main.html", iter.next().getPath()); + assertEquals("favicon.png", iter.next().getPath()); + assertFalse(iter.hasNext()); + } + + { + TestEntryIterator iter = archive.findByPath("ma"); + assertTrue(iter.hasNext()); + assertEquals("main.html", iter.next().getPath()); + assertFalse(iter.hasNext()); + } + + { + TestEntryIterator iter = archive.findByTitle("Test"); + assertTrue(iter.hasNext()); + assertEquals("main.html", iter.next().getPath()); + assertFalse(iter.hasNext()); + } } @Test @@ -82,6 +160,8 @@ public class test { throws JNIKiwixException, IOException, ZimFileFormatException { TestArchive archive = new TestArchive("small.zim"); testArchive(archive); + assertTrue(archive.check()); + assertEquals("small.zim", archive.getFilename()); archive.dispose(); // test reader with invalid zim file @@ -100,6 +180,8 @@ public class test { FileInputStream fis = new FileInputStream("small.zim"); TestArchive archive = new TestArchive(fis.getFD()); testArchive(archive); + assertTrue(archive.check()); + assertEquals("", archive.getFilename()); archive.dispose(); } @@ -109,28 +191,60 @@ public class test { File plainArchive = new File("small.zim"); FileInputStream fis = new FileInputStream("small.zim.embedded"); TestArchive archive = new TestArchive(fis.getFD(), 8, plainArchive.length()); + // This fails. See https://github.com/openzim/libzim/issues/812 + //assertTrue(archive.check()); testArchive(archive); + assertEquals("", archive.getFilename()); archive.dispose(); } - @Test - public void testLibrary() + private void testLibrary(TestLibrary lib) throws IOException { - TestLibrary lib = new TestLibrary(); - TestManager manager = new TestManager(lib); - String content = getTextFileContent("catalog.xml"); - manager.readOpds(content, "http://localhost"); assertEquals(lib.getBookCount(true, true), 1); String[] bookIds = lib.getBooksIds(); assertEquals(bookIds.length, 1); lib.filter(new Filter().local(true)); + assertTrue(Arrays.equals(lib.getBooksPublishers(), new String[]{"Publisher"})); + assertTrue(Arrays.equals(lib.getBooksCreators(), new String[]{"Creator"})); + System.out.println(Arrays.toString(lib.getBooksCategories())); + assertTrue(Arrays.equals(lib.getBooksCategories(), new String[]{"Category"})); + assertTrue(Arrays.equals(lib.getBooksLanguages(), new String[]{"eng"})); + + + // getArchiveById needs books with valid path. Which is not possible by definition if library is initialized by opds stream. + //assertEquals("86c91e51-55bf-8882-464e-072aca37a3e8", lib.getArchiveById("86c91e51-55bf-8882-464e-072aca37a3e8").getUuid()); TestBook book = lib.getBookById(bookIds[0]); assertEquals(book.getTitle(), "Test ZIM file"); - assertEquals(book.getTags(), "unit;test"); + assertEquals(book.getTags(), "_category:Category;_ftindex:yes;_ftindex:yes;_pictures:yes;_videos:yes;_details:yes"); assertEquals(book.getIllustration(48).width(), 48); - assertEquals(book.getIllustration(48).url(), "http://localhost/meta?name=favicon&content=small"); assertEquals(book.getUrl(), "http://localhost/small.zim"); + assertEquals(book.getDescription(), "Description"); + assertEquals(book.getCreator(), "Creator"); + assertEquals(book.getPublisher(), "Publisher"); + assertEquals(book.getFlavour(), ""); + assertEquals(book.getCategory(), "Category"); + assertEquals(book.getArticleCount(), 1); + assertEquals(book.getMediaCount(), 1); + assertEquals(book.getSize(), 66560); + Illustration[] illustrations = book.getIllustrations(); + assertEquals(1, illustrations.length); + + assertEquals(book.getTagStr("video"), ""); + } + + @Test + public void testLibrarySimple() throws IOException { + TestLibrary lib = new TestLibrary(); + TestManager manager = new TestManager(lib); + manager.addBookFromPath("small.zim", "small.zim", "http://localhost/small.zim", true); + testLibrary(lib); + String[] bookIds = lib.getBooksIds(); + TestBook book = lib.getBookById(bookIds[0]); + assertEquals(book.getIllustration(48).url(), ""); + assertEquals(book.getPath(), new File("small.zim").getAbsolutePath()); + assertEquals(book.getHumanReadableIdFromPath(), "small"); + assertTrue(book.isPathValid()); // remove book from library by id lib.removeBookById(bookIds[0]); @@ -138,6 +252,50 @@ public class test { assertEquals(bookIds.length, 0); } + @Test + public void testLibraryXml() throws IOException { + TestLibrary lib = new TestLibrary(); + TestManager manager = new TestManager(lib); + manager.readFile("library.xml"); + testLibrary(lib); + String[] bookIds = lib.getBooksIds(); + TestBook book = lib.getBookById(bookIds[0]); + assertEquals(book.getIllustration(48).url(), ""); + assertEquals(book.getPath(), new File("small.zim").getAbsolutePath()); + assertEquals(book.getHumanReadableIdFromPath(), "small"); + assertTrue(book.isPathValid()); + } + + @Test + public void testLibraryXmlContent() throws IOException { + TestLibrary lib = new TestLibrary(); + TestManager manager = new TestManager(lib); + String content = getTextFileContent("library.xml"); + manager.readXml(content, "library.xml"); + testLibrary(lib); + String[] bookIds = lib.getBooksIds(); + TestBook book = lib.getBookById(bookIds[0]); + assertEquals(book.getIllustration(48).url(), ""); + assertEquals(book.getPath(), new File("small.zim").getAbsolutePath()); + assertEquals(book.getHumanReadableIdFromPath(), "small"); + assertTrue(book.isPathValid()); + } + + @Test + public void testLibraryOPDS() throws IOException { + TestLibrary lib = new TestLibrary(); + TestManager manager = new TestManager(lib); + String content = getTextFileContent("catalog.xml"); + manager.readOpds(content, "http://localhost"); + testLibrary(lib); + String[] bookIds = lib.getBooksIds(); + TestBook book = lib.getBookById(bookIds[0]); + assertEquals(book.getIllustration(48).url(), "http://localhost/meta?name=favicon&content=small"); + assertEquals(book.getPath(), ""); + assertEquals(book.getHumanReadableIdFromPath(), ""); + assertFalse(book.isPathValid()); + } + @Test public void testServer() throws ZimFileFormatException, JNIKiwixException { TestArchive archive = new TestArchive("small.zim"); @@ -148,7 +306,13 @@ public class test { assertEquals(1, lib.getBookCount(true, true)); TestServer server = new TestServer(lib); server.setPort(8080); - assertEquals(true, server.start()); + server.setRoot("FOO"); + server.setAddress("127.0.0.1"); + server.setNbThreads(1); + server.setBlockExternalLinks(true); + server.setTaskbar(true, true); + assertTrue(server.start()); + server.stop(); } @Test @@ -176,6 +340,7 @@ public class test { assertEquals(bookmark.getUrl(), book.getUrl()); assertEquals(bookmark.getLanguage(), book.getLanguage()); assertEquals(bookmark.getDate(), book.getDate()); + assertEquals(bookmark.getBookTitle(), book.getName()); // remove bookmark from library lib.removeBookmark(bookmark.getBookId(), bookmark.getUrl()); bookmarkArray = lib.getBookmarks(true); @@ -187,21 +352,47 @@ public class test { TestArchive archive = new TestArchive("small.zim"); TestSearcher searcher = new TestSearcher(archive); - TestQuery query = new TestQuery("test"); + searcher.setVerbose(true); + TestQuery query = new TestQuery("test__"); + query.setQuery("test"); + TestSearch search = searcher.search(query); int estimatedMatches = (int) search.getEstimatedMatches(); assertEquals(1, estimatedMatches); TestSearchIterator iterator = search.getResults(0, estimatedMatches); + assertTrue(iterator.hasNext()); assertEquals("Test ZIM file", iterator.getTitle()); + assertEquals("main.html", iterator.getPath()); + assertEquals(100, iterator.getScore()); + assertEquals("Test ZIM file", iterator.getSnippet()); + assertEquals(3, iterator.getWordCount()); + assertEquals(0, iterator.getFileIndex()); + assertEquals(-1, iterator.getSize()); + assertEquals("e34f5109-ed0d-b93e-943d-06f7717c7340", iterator.getZimId()); + TestEntry entry = iterator.next(); + assertEquals("main.html", entry.getPath()); + + query.setGeorange(50,70,50); + assertEquals(0, searcher.search(query).getEstimatedMatches()); searcher.dispose(); + TestSearcher searcher2 = new TestSearcher(new TestArchive[0]); + searcher2.addArchive(archive); + assertEquals(1, searcher2.search(new TestQuery("test")).getEstimatedMatches()); + TestSuggestionSearcher suggestionSearcher = new TestSuggestionSearcher(archive); + suggestionSearcher.setVerbose(true); TestSuggestionSearch suggestionSearch = suggestionSearcher.suggest("test"); int matches = (int) suggestionSearch.getEstimatedMatches(); assertEquals(1, matches); TestSuggestionIterator results = suggestionSearch.getResults(0, matches); + assertTrue(results.hasNext()); TestSuggestionItem suggestionItem = results.next(); + assertFalse(results.hasNext()); assertEquals("Test ZIM file", suggestionItem.getTitle()); + assertEquals("main.html", suggestionItem.getPath()); + assertTrue(suggestionItem.hasSnippet()); + assertEquals("Test ZIM file", suggestionItem.getSnippet()); suggestionSearcher.dispose(); }