test_pdf.c (6412B)
1 /* 2 This file is part of libextractor. 3 Copyright (C) 2026 Vidyut Samanta and Christian Grothoff 4 5 libextractor is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published 7 by the Free Software Foundation; either version 3, or (at your 8 option) any later version. 9 10 libextractor is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with libextractor; see the file COPYING. If not, write to the 17 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 Boston, MA 02110-1301, USA. 19 */ 20 /** 21 * @file plugins/test_pdf.c 22 * @brief testcase for pdf plugin 23 * @author Christian Grothoff 24 */ 25 #include "platform.h" 26 #include "test_lib.h" 27 #include "test_paged_fulltext.h" 28 29 30 /** 31 * Check the full text of testdata/pdf_fulltext.pdf. 32 * 33 * @param data the full text 34 * @param data_len number of bytes in @a data 35 * @return 1 if acceptable 36 */ 37 static int 38 validate_pdf_fulltext (const void *data, 39 size_t data_len) 40 { 41 static const char *const pars[] = { 42 "Introduction", 43 "Paged documents scatter their words", 44 "The second paragraph is indented", 45 "Short paragraph number three.", 46 "The fourth paragraph", 47 "The fifth paragraph runs across the page break", 48 "The sixth paragraph", 49 "The seventh paragraph opens the two column part", 50 "The eighth paragraph continues in the left column", 51 "The ninth paragraph", 52 "The tenth paragraph is the first one of the right column", 53 "The eleventh paragraph concludes the document with a final remark.", 54 NULL 55 }; 56 static const char *const needles[] = { 57 "The caf\xc3\xa9 serves na\xc3\xafve guests.", 58 "the line numbers printed in the margins next to each column must be " 59 "dropped by the extractor because they are not part of the text at all.", 60 "apples, pears and plums that grow in an orchard near the river.", 61 "that guide ships safely through the night along rocky coasts.", 62 NULL 63 }; 64 static const char *const absent[] = { 65 NULL 66 }; 67 const char *s = data; 68 69 if (0 == check_form (s, data_len)) 70 { 71 fprintf (stderr, "Malformed full text\n"); 72 return 0; 73 } 74 return check_paragraphs (s, pars) && 75 check_contains (s, common_needles, common_absent) && 76 check_contains (s, needles, absent) && 77 check_no_numbers (s); 78 } 79 80 81 /** 82 * Main function for the PDF testcase. 83 * 84 * @param argc number of arguments (ignored) 85 * @param argv arguments (ignored) 86 * @return 0 on success 87 */ 88 int 89 main (int argc, char *argv[]) 90 { 91 struct SolutionData pdf_extract_sol[] = { 92 { 93 EXTRACTOR_METATYPE_MIMETYPE, 94 EXTRACTOR_METAFORMAT_UTF8, 95 "text/plain", 96 "application/pdf", 97 strlen ("application/pdf") + 1, 98 0 99 }, 100 { 101 EXTRACTOR_METATYPE_TITLE, 102 EXTRACTOR_METAFORMAT_UTF8, 103 "text/plain", 104 "GNU libextractor PDF Test", 105 strlen ("GNU libextractor PDF Test") + 1, 106 0 107 }, 108 { 109 EXTRACTOR_METATYPE_SUBJECT, 110 EXTRACTOR_METAFORMAT_UTF8, 111 "text/plain", 112 "Metadata extraction", 113 strlen ("Metadata extraction") + 1, 114 0 115 }, 116 { 117 EXTRACTOR_METATYPE_KEYWORDS, 118 EXTRACTOR_METAFORMAT_UTF8, 119 "text/plain", 120 "PDF, libextractor, test", 121 strlen ("PDF, libextractor, test") + 1, 122 0 123 }, 124 { 125 EXTRACTOR_METATYPE_AUTHOR_NAME, 126 EXTRACTOR_METAFORMAT_UTF8, 127 "text/plain", 128 "Vidyut Samanta", 129 strlen ("Vidyut Samanta") + 1, 130 0 131 }, 132 { 133 EXTRACTOR_METATYPE_CREATED_BY_SOFTWARE, 134 EXTRACTOR_METAFORMAT_UTF8, 135 "text/plain", 136 "WritePDF", 137 strlen ("WritePDF") + 1, 138 0 139 }, 140 { 141 EXTRACTOR_METATYPE_PRODUCED_BY_SOFTWARE, 142 EXTRACTOR_METAFORMAT_UTF8, 143 "text/plain", 144 "libextractor testsuite", 145 strlen ("libextractor testsuite") + 1, 146 0 147 }, 148 { 149 EXTRACTOR_METATYPE_FORMAT, 150 EXTRACTOR_METAFORMAT_UTF8, 151 "text/plain", 152 "PDF 1.4", 153 strlen ("PDF 1.4") + 1, 154 0 155 }, 156 { 157 EXTRACTOR_METATYPE_PAGE_COUNT, 158 EXTRACTOR_METAFORMAT_UTF8, 159 "text/plain", 160 "1", 161 strlen ("1") + 1, 162 0 163 }, 164 { 165 EXTRACTOR_METATYPE_CREATION_DATE, 166 EXTRACTOR_METAFORMAT_UTF8, 167 "text/plain", 168 "2020-01-15 12:30:00", 169 strlen ("2020-01-15 12:30:00") + 1, 170 0 171 }, 172 { 173 EXTRACTOR_METATYPE_MODIFICATION_DATE, 174 EXTRACTOR_METAFORMAT_UTF8, 175 "text/plain", 176 "2020-01-16 08:00:00", 177 strlen ("2020-01-16 08:00:00") + 1, 178 0 179 }, 180 { 0, 0, NULL, NULL, 0, -1 } 181 }; 182 struct SolutionData pdf_fulltext_sol[] = { 183 { 184 EXTRACTOR_METATYPE_MIMETYPE, 185 EXTRACTOR_METAFORMAT_UTF8, 186 "text/plain", 187 "application/pdf", 188 strlen ("application/pdf") + 1, 189 0 190 }, 191 { 192 EXTRACTOR_METATYPE_PAGE_COUNT, 193 EXTRACTOR_METAFORMAT_UTF8, 194 "text/plain", 195 "3", 196 strlen ("3") + 1, 197 0 198 }, 199 { 200 EXTRACTOR_METATYPE_FULL_TEXT, 201 EXTRACTOR_METAFORMAT_UTF8, 202 "text/plain", 203 "^Introduction\n\nPaged documents scatter", 204 0, 205 0, 206 1, 207 &validate_pdf_fulltext 208 }, 209 { 0, 0, NULL, NULL, 0, -1 } 210 }; 211 struct ProblemSet ps[] = { 212 { "testdata/pdf_extract.pdf", 213 pdf_extract_sol }, 214 { NULL, NULL } 215 }; 216 struct ProblemSet ps_ft[] = { 217 { "testdata/pdf_extract.pdf", 218 pdf_extract_sol }, 219 { "testdata/pdf_fulltext.pdf", 220 pdf_fulltext_sol }, 221 { NULL, NULL } 222 }; 223 int ret = 0; 224 225 ret |= ET_main ("pdf", ps); 226 /* without the option, there must be no full text */ 227 ret |= check_fulltext_count ("pdf", 228 "testdata/pdf_fulltext.pdf", 229 0); 230 ret |= ET_main ("pdf(fulltext)", ps_ft); 231 /* a document without text has no full text either */ 232 ret |= check_fulltext_count ("pdf(fulltext)", 233 "testdata/pdf_extract.pdf", 234 0); 235 ret |= check_fulltext_count ("pdf(fulltext)", 236 "testdata/pdf_fulltext.pdf", 237 1); 238 return ret; 239 } 240 241 242 /* end of test_pdf.c */