Calibre OPDS (and HTML) PHP Server : web-based light alternative to Calibre content server / Calibre2OPDS to serve ebooks (epub, mobi, pdf, ...) http://blog.slucas.fr/en/oss/calibre-opds-php-server
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

605 lines
21KB

  1. <?php
  2. /**
  3. * COPS (Calibre OPDS PHP Server) test file
  4. *
  5. * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
  6. * @author Sébastien Lucas <sebastien@slucas.fr>
  7. */
  8. require_once (dirname(__FILE__) . "/config_test.php");
  9. require_once (dirname(__FILE__) . "/../book.php");
  10. require_once (dirname(__FILE__) . "/../JSON_renderer.php");
  11. /*
  12. Publishers:
  13. id:2 (2 books) Macmillan and Co. London: Lewis Caroll
  14. id:3 (2 books) D. Appleton and Company Alexander Dumas
  15. id:4 (1 book) Macmillan Publishers USA: Jack London
  16. id:5 (1 book) Pierson's Magazine: H. G. Wells
  17. id:6 (8 books) Strand Magazine: Arthur Conan Doyle
  18. */
  19. define ("TEST_THUMBNAIL", dirname(__FILE__) . "/thumbnail.jpg");
  20. define ("COVER_WIDTH", 400);
  21. define ("COVER_HEIGHT", 600);
  22. class BookTest extends PHPUnit_Framework_TestCase
  23. {
  24. public static function setUpBeforeClass()
  25. {
  26. $book = Book::getBookById(2);
  27. if (!is_dir ($book->path)) {
  28. mkdir ($book->path, 0777, true);
  29. }
  30. $im = imagecreatetruecolor(COVER_WIDTH, COVER_HEIGHT);
  31. $text_color = imagecolorallocate($im, 255, 0, 0);
  32. imagestring($im, 1, 5, 5, 'Book cover', $text_color);
  33. imagejpeg ($im, $book->path . "/cover.jpg", 80);
  34. }
  35. public static function tearDownAfterClass()
  36. {
  37. $book = Book::getBookById(2);
  38. if (!file_exists ($book->path . "/cover.jpg")) {
  39. return;
  40. }
  41. unlink ($book->path . "/cover.jpg");
  42. rmdir ($book->path);
  43. rmdir (dirname ($book->path));
  44. }
  45. public function testGetBookCount ()
  46. {
  47. $this->assertEquals (15, Book::getBookCount ());
  48. }
  49. public function testGetCount ()
  50. {
  51. $entryArray = Book::getCount ();
  52. $this->assertEquals (2, count($entryArray));
  53. $entryAllBooks = $entryArray [0];
  54. $this->assertEquals ("Alphabetical index of the 15 books", $entryAllBooks->content);
  55. $entryRecentBooks = $entryArray [1];
  56. $this->assertEquals ("50 most recent books", $entryRecentBooks->content);
  57. }
  58. public function testGetCountRecent ()
  59. {
  60. global $config;
  61. $config['cops_recentbooks_limit'] = 0;
  62. $entryArray = Book::getCount ();
  63. $this->assertEquals (1, count($entryArray));
  64. $config['cops_recentbooks_limit'] = 2;
  65. $entryArray = Book::getCount ();
  66. $entryRecentBooks = $entryArray [1];
  67. $this->assertEquals ("2 most recent books", $entryRecentBooks->content);
  68. $config['cops_recentbooks_limit'] = 50;
  69. }
  70. public function testGetBooksByAuthor ()
  71. {
  72. // All book by Arthur Conan Doyle
  73. global $config;
  74. $config['cops_max_item_per_page'] = 5;
  75. list ($entryArray, $totalNumber) = Book::getBooksByAuthor (1, 1);
  76. $this->assertEquals (5, count($entryArray));
  77. $this->assertEquals (8, $totalNumber);
  78. list ($entryArray, $totalNumber) = Book::getBooksByAuthor (1, 2);
  79. $this->assertEquals (3, count($entryArray));
  80. $this->assertEquals (8, $totalNumber);
  81. $config['cops_max_item_per_page'] = -1;
  82. list ($entryArray, $totalNumber) = Book::getBooksByAuthor (1, -1);
  83. $this->assertEquals (8, count($entryArray));
  84. $this->assertEquals (-1, $totalNumber);
  85. }
  86. public function testGetBooksBySeries ()
  87. {
  88. // All book from the Sherlock Holmes series
  89. list ($entryArray, $totalNumber) = Book::getBooksBySeries (1, -1);
  90. $this->assertEquals (7, count($entryArray));
  91. $this->assertEquals (-1, $totalNumber);
  92. }
  93. public function testGetBooksByPublisher ()
  94. {
  95. // All books from Strand Magazine
  96. list ($entryArray, $totalNumber) = Book::getBooksByPublisher (6, -1);
  97. $this->assertEquals (8, count($entryArray));
  98. $this->assertEquals (-1, $totalNumber);
  99. }
  100. public function testGetBooksByTag ()
  101. {
  102. // All book with the Fiction tag
  103. list ($entryArray, $totalNumber) = Book::getBooksByTag (1, -1);
  104. $this->assertEquals (14, count($entryArray));
  105. $this->assertEquals (-1, $totalNumber);
  106. }
  107. public function testGetBooksByLanguage ()
  108. {
  109. // All english book (= all books)
  110. list ($entryArray, $totalNumber) = Book::getBooksByLanguage (1, -1);
  111. $this->assertEquals (14, count($entryArray));
  112. $this->assertEquals (-1, $totalNumber);
  113. }
  114. public function testGetAllBooks ()
  115. {
  116. // All books by first letter
  117. $entryArray = Book::getAllBooks ();
  118. $this->assertCount (9, $entryArray);
  119. }
  120. public function testGetBooksByStartingLetter ()
  121. {
  122. // All books by first letter
  123. list ($entryArray, $totalNumber) = Book::getBooksByStartingLetter ("T", -1);
  124. $this->assertEquals (-1, $totalNumber);
  125. $this->assertCount (3, $entryArray);
  126. }
  127. public function testGetBookByDataId ()
  128. {
  129. $book = Book::getBookByDataId (17);
  130. $this->assertEquals ("Alice's Adventures in Wonderland", $book->getTitle ());
  131. }
  132. public function testGetAllRecentBooks ()
  133. {
  134. // All recent books
  135. global $config;
  136. $config['cops_recentbooks_limit'] = 2;
  137. $entryArray = Book::getAllRecentBooks ();
  138. $this->assertCount (2, $entryArray);
  139. $config['cops_recentbooks_limit'] = 50;
  140. $entryArray = Book::getAllRecentBooks ();
  141. $this->assertCount (15, $entryArray);
  142. }
  143. /**
  144. * @dataProvider providerPublicationDate
  145. */
  146. public function testGetPubDate ($pubdate, $expectedYear)
  147. {
  148. $book = Book::getBookById(2);
  149. $book->pubdate = $pubdate;
  150. $this->assertEquals($expectedYear, $book->getPubDate());
  151. }
  152. public function providerPublicationDate() {
  153. return array(
  154. array('2010-10-05 22:00:00+00:00', '2010'),
  155. array('1982-11-15 13:05:29.908657+00:00', '1982'),
  156. array('1562-10-05 00:00:00+00:00', '1562'),
  157. array('0100-12-31 23:00:00+00:00', ''),
  158. array('', ''),
  159. array(NULL, '')
  160. );
  161. }
  162. public function testGetBookById ()
  163. {
  164. // also check most of book's class methods
  165. $book = Book::getBookById(2);
  166. $linkArray = $book->getLinkArray ();
  167. $this->assertCount (5, $linkArray);
  168. $this->assertEquals ("The Return of Sherlock Holmes", $book->getTitle ());
  169. $this->assertEquals ("urn:uuid:87ddbdeb-1e27-4d06-b79b-4b2a3bfc6a5f", $book->getEntryId ());
  170. $this->assertEquals ("index.php?page=13&id=2", $book->getDetailUrl ());
  171. $this->assertEquals ("Arthur Conan Doyle", $book->getAuthorsName ());
  172. $this->assertEquals ("Fiction, Mystery & Detective, Short Stories", $book->getTagsName ());
  173. $this->assertEquals ('<p class="description">The Return of Sherlock Holmes is a collection of 13 Sherlock Holmes stories, originally published in 1903-1904, by Arthur Conan Doyle.<br />The book was first published on March 7, 1905 by Georges Newnes, Ltd and in a Colonial edition by Longmans. 30,000 copies were made of the initial print run. The US edition by McClure, Phillips &amp; Co. added another 28,000 to the run.<br />This was the first Holmes collection since 1893, when Holmes had "died" in "The Adventure of the Final Problem". Having published The Hound of the Baskervilles in 1901–1902 (although setting it before Holmes\' death) Doyle came under intense pressure to revive his famous character.</p>', $book->getComment (false));
  174. $this->assertEquals ("English", $book->getLanguages ());
  175. $this->assertEquals ("Strand Magazine", $book->getPublisher()->name);
  176. }
  177. public function testGetBookById_NotFound ()
  178. {
  179. $book = Book::getBookById(666);
  180. $this->assertNull ($book);
  181. }
  182. public function testGetRating_FiveStars ()
  183. {
  184. $book = Book::getBookById(2);
  185. $this->assertEquals ("&#9733;&#9733;&#9733;&#9733;&#9733;", $book->getRating ());
  186. }
  187. public function testGetRating_FourStars ()
  188. {
  189. $book = Book::getBookById(2);
  190. $book->rating = 8;
  191. // 4 filled stars and one empty
  192. $this->assertEquals ("&#9733;&#9733;&#9733;&#9733;&#9734;", $book->getRating ());
  193. }
  194. public function testGetRating_NoStars_Zero ()
  195. {
  196. $book = Book::getBookById(2);
  197. $book->rating = 0;
  198. $this->assertEquals ("", $book->getRating ());
  199. }
  200. public function testGetRating_NoStars_Null ()
  201. {
  202. $book = Book::getBookById(2);
  203. $book->rating = NULL;
  204. $this->assertEquals ("", $book->getRating ());
  205. }
  206. public function testBookGetLinkArrayWithUrlRewriting ()
  207. {
  208. global $config;
  209. $book = Book::getBookById(2);
  210. $config['cops_use_url_rewriting'] = "1";
  211. $linkArray = $book->getLinkArray ();
  212. foreach ($linkArray as $link) {
  213. if ($link->rel == Link::OPDS_ACQUISITION_TYPE && $link->title == "EPUB" ) {
  214. $this->assertEquals ("download/1/The+Return+of+Sherlock+Holmes+-+Arthur+Conan+Doyle.epub", $link->href);
  215. return;
  216. }
  217. }
  218. $this->fail ();
  219. }
  220. public function testBookGetLinkArrayWithoutUrlRewriting ()
  221. {
  222. global $config;
  223. $book = Book::getBookById(2);
  224. $config['cops_use_url_rewriting'] = "0";
  225. $linkArray = $book->getLinkArray ();
  226. foreach ($linkArray as $link) {
  227. if ($link->rel == Link::OPDS_ACQUISITION_TYPE && $link->title == "EPUB" ) {
  228. $this->assertEquals ("fetch.php?data=1&type=epub&id=2", $link->href);
  229. return;
  230. }
  231. }
  232. $this->fail ();
  233. }
  234. public function testGetThumbnailNotNeeded ()
  235. {
  236. $book = Book::getBookById(2);
  237. $this->assertFalse ($book->getThumbnail (NULL, NULL, NULL));
  238. // Current cover is 400*600
  239. $this->assertFalse ($book->getThumbnail (COVER_WIDTH, NULL, NULL));
  240. $this->assertFalse ($book->getThumbnail (COVER_WIDTH + 1, NULL, NULL));
  241. $this->assertFalse ($book->getThumbnail (NULL, COVER_HEIGHT, NULL));
  242. $this->assertFalse ($book->getThumbnail (NULL, COVER_HEIGHT + 1, NULL));
  243. }
  244. /**
  245. * @dataProvider providerThumbnail
  246. */
  247. public function testGetThumbnailByWidth ($width, $height, $expectedWidth, $expectedHeight)
  248. {
  249. $book = Book::getBookById(2);
  250. $this->assertTrue ($book->getThumbnail ($width, $height, TEST_THUMBNAIL));
  251. $size = GetImageSize(TEST_THUMBNAIL);
  252. $this->assertEquals ($expectedWidth, $size [0]);
  253. $this->assertEquals ($expectedHeight, $size [1]);
  254. unlink (TEST_THUMBNAIL);
  255. }
  256. public function providerThumbnail ()
  257. {
  258. return array (
  259. array (164, NULL, 164, 246),
  260. array (NULL, 164, 109, 164)
  261. );
  262. }
  263. public function testGetMostInterestingDataToSendToKindle_WithMOBI ()
  264. {
  265. // Get Alice (available as MOBI, PDF, EPUB in that order)
  266. $book = Book::getBookById(17);
  267. $data = $book->GetMostInterestingDataToSendToKindle ();
  268. $this->assertEquals ("MOBI", $data->format);
  269. }
  270. public function testGetMostInterestingDataToSendToKindle_WithPdf ()
  271. {
  272. // Get Alice (available as MOBI, PDF, EPUB in that order)
  273. $book = Book::getBookById(17);
  274. $book->GetMostInterestingDataToSendToKindle ();
  275. array_shift ($book->datas);
  276. $data = $book->GetMostInterestingDataToSendToKindle ();
  277. $this->assertEquals ("PDF", $data->format);
  278. }
  279. public function testGetMostInterestingDataToSendToKindle_WithEPUB ()
  280. {
  281. // Get Alice (available as MOBI, PDF, EPUB in that order)
  282. $book = Book::getBookById(17);
  283. $book->GetMostInterestingDataToSendToKindle ();
  284. array_shift ($book->datas);
  285. array_shift ($book->datas);
  286. $data = $book->GetMostInterestingDataToSendToKindle ();
  287. $this->assertEquals ("EPUB", $data->format);
  288. }
  289. public function testGetDataById ()
  290. {
  291. global $config;
  292. // Get Alice MOBI=>17, PDF=>19, EPUB=>20
  293. $book = Book::getBookById(17);
  294. $mobi = $book->getDataById (17);
  295. $this->assertEquals ("MOBI", $mobi->format);
  296. $epub = $book->getDataById (20);
  297. $this->assertEquals ("EPUB", $epub->format);
  298. $this->assertEquals ("Carroll, Lewis - Alice's Adventures in Wonderland.epub", $epub->getUpdatedFilenameEpub ());
  299. $this->assertEquals ("Carroll, Lewis - Alice's Adventures in Wonderland.kepub.epub", $epub->getUpdatedFilenameKepub ());
  300. $this->assertEquals (dirname(__FILE__) . "/BaseWithSomeBooks/Lewis Carroll/Alice's Adventures in Wonderland (17)/Alice's Adventures in Wonderland - Lewis Carroll.epub", $epub->getLocalPath ());
  301. $config['cops_use_url_rewriting'] = "1";
  302. $config['cops_provide_kepub'] = "1";
  303. $_SERVER["HTTP_USER_AGENT"] = "Kobo";
  304. $this->assertEquals ("download/20/Carroll%2C+Lewis+-+Alice%27s+Adventures+in+Wonderland.kepub.epub", $epub->getHtmlLink ());
  305. $this->assertEquals ("download/17/Alice%27s+Adventures+in+Wonderland+-+Lewis+Carroll.mobi", $mobi->getHtmlLink ());
  306. $_SERVER["HTTP_USER_AGENT"] = "Firefox";
  307. $this->assertEquals ("download/20/Alice%27s+Adventures+in+Wonderland+-+Lewis+Carroll.epub", $epub->getHtmlLink ());
  308. $config['cops_use_url_rewriting'] = "0";
  309. $this->assertEquals ("fetch.php?data=20&type=epub&id=17", $epub->getHtmlLink ());
  310. }
  311. public function testGetFilePath_Cover () {
  312. $book = Book::getBookById(17);
  313. $this->assertEquals ("Lewis Carroll/Alice's Adventures in Wonderland (17)/cover.jpg", $book->getFilePath ("jpg", NULL, true));
  314. }
  315. public function testGetFilePath_Epub () {
  316. $book = Book::getBookById(17);
  317. $this->assertEquals ("Lewis Carroll/Alice's Adventures in Wonderland (17)/Alice's Adventures in Wonderland - Lewis Carroll.epub", $book->getFilePath ("epub", 20, true));
  318. }
  319. public function testGetFilePath_Mobi () {
  320. $book = Book::getBookById(17);
  321. $this->assertEquals ("Lewis Carroll/Alice's Adventures in Wonderland (17)/Alice's Adventures in Wonderland - Lewis Carroll.mobi", $book->getFilePath ("mobi", 17, true));
  322. }
  323. public function testGetDataFormat_EPUB () {
  324. $book = Book::getBookById(17);
  325. // Get Alice MOBI=>17, PDF=>19, EPUB=>20
  326. $data = $book->getDataFormat ("EPUB");
  327. $this->assertEquals (20, $data->id);
  328. }
  329. public function testGetDataFormat_MOBI () {
  330. $book = Book::getBookById(17);
  331. // Get Alice MOBI=>17, PDF=>19, EPUB=>20
  332. $data = $book->getDataFormat ("MOBI");
  333. $this->assertEquals (17, $data->id);
  334. }
  335. public function testGetDataFormat_PDF () {
  336. $book = Book::getBookById(17);
  337. // Get Alice MOBI=>17, PDF=>19, EPUB=>20
  338. $data = $book->getDataFormat ("PDF");
  339. $this->assertEquals (19, $data->id);
  340. }
  341. public function testGetDataFormat_NonAvailable () {
  342. $book = Book::getBookById(17);
  343. // Get Alice MOBI=>17, PDF=>19, EPUB=>20
  344. $this->assertFalse ($book->getDataFormat ("FB2"));
  345. }
  346. public function testGetMimeType_EPUB () {
  347. $book = Book::getBookById(17);
  348. // Get Alice MOBI=>17, PDF=>19, EPUB=>20
  349. $data = $book->getDataFormat ("EPUB");
  350. $this->assertEquals ("application/epub+zip", $data->getMimeType ());
  351. }
  352. public function testGetMimeType_MOBI () {
  353. $book = Book::getBookById(17);
  354. // Get Alice MOBI=>17, PDF=>19, EPUB=>20
  355. $data = $book->getDataFormat ("MOBI");
  356. $this->assertEquals ("application/x-mobipocket-ebook", $data->getMimeType ());
  357. }
  358. public function testGetMimeType_PDF () {
  359. $book = Book::getBookById(17);
  360. // Get Alice MOBI=>17, PDF=>19, EPUB=>20
  361. $data = $book->getDataFormat ("PDF");
  362. $this->assertEquals ("application/pdf", $data->getMimeType ());
  363. }
  364. public function testGetMimeType_Finfo () {
  365. $book = Book::getBookById(17);
  366. // Get Alice MOBI=>17, PDF=>19, EPUB=>20
  367. $data = $book->getDataFormat ("PDF");
  368. $this->assertEquals ("application/pdf", $data->getMimeType ());
  369. // Alter a data to make a test for finfo_file if enabled
  370. $data->extension = "ico";
  371. $data->format = "ICO";
  372. $data->name = "favicon";
  373. $data->book->path = realpath (dirname(__FILE__) . "/../");
  374. if (function_exists('finfo_open') === true) {
  375. $this->assertEquals ("image/x-icon", $data->getMimeType ());
  376. } else {
  377. $this->assertEquals ("application/octet-stream", $data->getMimeType ());
  378. }
  379. }
  380. public function testTypeaheadSearch_Tag ()
  381. {
  382. $_GET["page"] = Base::PAGE_OPENSEARCH_QUERY;
  383. $_GET["query"] = "fic";
  384. $_GET["search"] = "1";
  385. $array = JSONRenderer::getJson ();
  386. $this->assertCount (3, $array);
  387. $this->assertEquals ("2 tags", $array[0]["title"]);
  388. $this->assertEquals ("Fiction", $array[1]["title"]);
  389. $this->assertEquals ("Science Fiction", $array[2]["title"]);
  390. $_GET["query"] = NULL;
  391. $_GET["search"] = NULL;
  392. }
  393. public function testTypeaheadSearch_BookAndAuthor ()
  394. {
  395. $_GET["page"] = Base::PAGE_OPENSEARCH_QUERY;
  396. $_GET["query"] = "car";
  397. $_GET["search"] = "1";
  398. $array = JSONRenderer::getJson ();
  399. $this->assertCount (4, $array);
  400. $this->assertEquals ("1 book", $array[0]["title"]);
  401. $this->assertEquals ("A Study in Scarlet", $array[1]["title"]);
  402. $this->assertEquals ("1 author", $array[2]["title"]);
  403. $this->assertEquals ("Carroll, Lewis", $array[3]["title"]);
  404. $_GET["query"] = NULL;
  405. $_GET["search"] = NULL;
  406. }
  407. public function testTypeaheadSearch_AuthorAndSeries ()
  408. {
  409. $_GET["page"] = Base::PAGE_OPENSEARCH_QUERY;
  410. $_GET["query"] = "art";
  411. $_GET["search"] = "1";
  412. $array = JSONRenderer::getJson ();
  413. $this->assertCount (5, $array);
  414. $this->assertEquals ("1 author", $array[0]["title"]);
  415. $this->assertEquals ("Doyle, Arthur Conan", $array[1]["title"]);
  416. $this->assertEquals ("2 series", $array[2]["title"]);
  417. $this->assertEquals ("D'Artagnan Romances", $array[3]["title"]);
  418. $_GET["query"] = NULL;
  419. $_GET["search"] = NULL;
  420. }
  421. public function testTypeaheadSearch_Publisher ()
  422. {
  423. $_GET["page"] = Base::PAGE_OPENSEARCH_QUERY;
  424. $_GET["query"] = "Macmillan";
  425. $_GET["search"] = "1";
  426. $array = JSONRenderer::getJson ();
  427. $this->assertCount (3, $array);
  428. $this->assertEquals ("2 publishers", $array[0]["title"]);
  429. $this->assertEquals ("Macmillan and Co. London", $array[1]["title"]);
  430. $this->assertEquals ("Macmillan Publishers USA", $array[2]["title"]);
  431. $_GET["query"] = NULL;
  432. $_GET["search"] = NULL;
  433. }
  434. public function testTypeaheadSearchWithIgnored_SingleCategory ()
  435. {
  436. global $config;
  437. $_GET["page"] = Base::PAGE_OPENSEARCH_QUERY;
  438. $_GET["query"] = "car";
  439. $_GET["search"] = "1";
  440. $config ['cops_ignored_categories'] = array ("author");
  441. $array = JSONRenderer::getJson ();
  442. $this->assertCount (2, $array);
  443. $this->assertEquals ("1 book", $array[0]["title"]);
  444. $this->assertEquals ("A Study in Scarlet", $array[1]["title"]);
  445. $_GET["query"] = NULL;
  446. $_GET["search"] = NULL;
  447. }
  448. public function testTypeaheadSearchWithIgnored_MultipleCategory ()
  449. {
  450. global $config;
  451. $_GET["page"] = Base::PAGE_OPENSEARCH_QUERY;
  452. $_GET["query"] = "art";
  453. $_GET["search"] = "1";
  454. $config ['cops_ignored_categories'] = array ("series");
  455. $array = JSONRenderer::getJson ();
  456. $this->assertCount (2, $array);
  457. $this->assertEquals ("1 author", $array[0]["title"]);
  458. $this->assertEquals ("Doyle, Arthur Conan", $array[1]["title"]);
  459. $_GET["query"] = NULL;
  460. $_GET["search"] = NULL;
  461. }
  462. public function testTypeaheadSearchMultiDatabase ()
  463. {
  464. global $config;
  465. $_GET["page"] = Base::PAGE_OPENSEARCH_QUERY;
  466. $_GET["query"] = "art";
  467. $_GET["search"] = "1";
  468. $_GET["multi"] = "1";
  469. $config['calibre_directory'] = array ("Some books" => dirname(__FILE__) . "/BaseWithSomeBooks/",
  470. "One book" => dirname(__FILE__) . "/BaseWithOneBook/");
  471. $array = JSONRenderer::getJson ();
  472. $this->assertCount (5, $array);
  473. $this->assertEquals ("Some books", $array[0]["title"]);
  474. $this->assertEquals ("1 author", $array[1]["title"]);
  475. $this->assertEquals ("2 series", $array[2]["title"]);
  476. $this->assertEquals ("One book", $array[3]["title"]);
  477. $this->assertEquals ("1 book", $array[4]["title"]);
  478. $_GET["query"] = NULL;
  479. $_GET["search"] = NULL;
  480. }
  481. public function tearDown () {
  482. Base::clearDb ();
  483. }
  484. }