diff --git a/reader/browser/BrowserMagniFier.h b/reader/browser/BrowserMagniFier.h index ba4dbc12..cc03e774 100644 --- a/reader/browser/BrowserMagniFier.h +++ b/reader/browser/BrowserMagniFier.h @@ -20,7 +20,7 @@ typedef struct MagnifierInfo_t { double scaleFactor; BrowserPage *page; } MagnifierInfo_t; -Q_DECLARE_METATYPE(MagnifierInfo_t) +Q_DECLARE_METATYPE(MagnifierInfo_t) // LCOV_EXCL_LINE /** * @brief 放大镜任务线程 diff --git a/tests/browser/ut_pagerenderthread.cpp b/tests/browser/ut_pagerenderthread.cpp index 9ad521e0..80b123e5 100644 --- a/tests/browser/ut_pagerenderthread.cpp +++ b/tests/browser/ut_pagerenderthread.cpp @@ -6,6 +6,8 @@ #include "PageRenderThread.h" #include "DocSheet.h" #include "BrowserPage.h" +#include "SheetRenderer.h" +#include "SideBarImageViewModel.h" #include "stub.h" #include @@ -33,7 +35,6 @@ void TestPageRenderThread::SetUp() void TestPageRenderThread::TearDown() { - PageRenderThread::destroyForever(); } /**********桩函数*************/ @@ -55,6 +56,43 @@ void run_stub() g_funcName = __FUNCTION__; qInfo() << "chendu" << __FUNCTION__; } + +// Stubs for methods called inside onDoc*Finished slots (true-branch). +// When task.sheet exists, the slot calls task.page/model/renderer methods. +// These stubs are installed so nullptr page/model/renderer won't crash. +static void handleRenderFinished_stub(const int &, const QPixmap &, const QRect &) +{ + g_funcName = __FUNCTION__; +} + +static void handleWordLoaded_stub(const QList &) +{ + g_funcName = __FUNCTION__; +} + +static void handleAnnotationLoaded_stub(const QList &) +{ + g_funcName = __FUNCTION__; +} + +static void handleRenderThumbnail_stub(int, QPixmap) +{ + g_funcName = __FUNCTION__; +} + +static void handleOpened_stub(deepin_reader::Document::Error, deepin_reader::Document *, QList) +{ + g_funcName = __FUNCTION__; +} + +// Makes DocSheet::existSheet() return true so the onDoc*Finished slots +// take the "sheet exists" branch without needing a real DocSheet (whose +// destructor would otherwise start the render thread and deadlock the test). +static bool existSheet_true_stub(DocSheet *) +{ + return true; +} + /*********测试用例**********/ //TEST_F(TestPageRenderThread, UT_PageRenderThread_clearImageTasks_001) //{ @@ -78,3 +116,331 @@ void run_stub() // EXPECT_TRUE(m_tester->clearImageTasks(docsheet, browserpage, 0)); //} + +//====================================================================== +// onDoc*Finished slots, false-branch (sheet == nullptr, existSheet false) +//====================================================================== + +// Tests onDocPageNormalImageTaskFinished when sheet does not exist. +TEST_F(TestPageRenderThread, UT_PageRenderThread_onDocPageNormalImageTaskFinished_001) +{ + DocPageNormalImageTask task; + task.sheet = nullptr; + task.page = nullptr; + task.pixmapId = 0; + QPixmap pix; + m_tester->onDocPageNormalImageTaskFinished(task, pix); + SUCCEED(); +} + +// Tests onDocPageSliceImageTaskFinished when sheet does not exist. +TEST_F(TestPageRenderThread, UT_PageRenderThread_onDocPageSliceImageTaskFinished_001) +{ + DocPageSliceImageTask task; + task.sheet = nullptr; + task.page = nullptr; + task.pixmapId = 0; + QPixmap pix; + m_tester->onDocPageSliceImageTaskFinished(task, pix); + SUCCEED(); +} + +// Tests onDocPageBigImageTaskFinished when sheet does not exist. +TEST_F(TestPageRenderThread, UT_PageRenderThread_onDocPageBigImageTaskFinished_001) +{ + DocPageBigImageTask task; + task.sheet = nullptr; + task.page = nullptr; + task.pixmapId = 0; + QPixmap pix; + m_tester->onDocPageBigImageTaskFinished(task, pix); + SUCCEED(); +} + +// Tests onDocPageWordTaskFinished when sheet does not exist. +TEST_F(TestPageRenderThread, UT_PageRenderThread_onDocPageWordTaskFinished_001) +{ + DocPageWordTask task; + task.sheet = nullptr; + task.page = nullptr; + QList words; + m_tester->onDocPageWordTaskFinished(task, words); + SUCCEED(); +} + +// Tests onDocPageAnnotationTaskFinished when sheet does not exist. +TEST_F(TestPageRenderThread, UT_PageRenderThread_onDocPageAnnotationTaskFinished_001) +{ + DocPageAnnotationTask task; + task.sheet = nullptr; + task.page = nullptr; + QList annots; + m_tester->onDocPageAnnotationTaskFinished(task, annots); + SUCCEED(); +} + +// Tests onDocPageThumbnailTask when sheet does not exist. +TEST_F(TestPageRenderThread, UT_PageRenderThread_onDocPageThumbnailTask_001) +{ + DocPageThumbnailTask task; + task.sheet = nullptr; + task.model = nullptr; + task.index = 0; + QPixmap pix; + m_tester->onDocPageThumbnailTask(task, pix); + SUCCEED(); +} + +// Tests onDocOpenTask when sheet does not exist. +TEST_F(TestPageRenderThread, UT_PageRenderThread_onDocOpenTask_001) +{ + DocOpenTask task; + task.sheet = nullptr; + task.renderer = nullptr; + QList pages; + m_tester->onDocOpenTask(task, deepin_reader::Document::NoError, nullptr, pages); + SUCCEED(); +} + +//====================================================================== +// onDoc*Finished slots, true-branch (real sheet, existSheet true) +// Stubs are installed so the forwarded calls on null page/model/renderer +// don't crash. +//====================================================================== + +// Tests onDocPageNormalImageTaskFinished when sheet exists; forwards to +// BrowserPage::handleRenderFinished (stubbed). +TEST_F(TestPageRenderThread, UT_PageRenderThread_onDocPageNormalImageTaskFinished_002) +{ + Stub s; + s.set(ADDR(DocSheet, existSheet), existSheet_true_stub); + s.set(ADDR(BrowserPage, handleRenderFinished), handleRenderFinished_stub); + + DocPageNormalImageTask task; + task.sheet = nullptr; // existSheet is stubbed to return true anyway + task.page = nullptr; // stub will be invoked, nullptr this is ignored + task.pixmapId = 1; + QPixmap pix; + m_tester->onDocPageNormalImageTaskFinished(task, pix); + EXPECT_TRUE(g_funcName == "handleRenderFinished_stub"); +} + +// Tests onDocPageSliceImageTaskFinished when sheet exists; forwards to +// BrowserPage::handleRenderFinished with slice (stubbed). +TEST_F(TestPageRenderThread, UT_PageRenderThread_onDocPageSliceImageTaskFinished_002) +{ + Stub s; + s.set(ADDR(DocSheet, existSheet), existSheet_true_stub); + s.set(ADDR(BrowserPage, handleRenderFinished), handleRenderFinished_stub); + + DocPageSliceImageTask task; + task.sheet = nullptr; + task.page = nullptr; + task.pixmapId = 2; + task.slice = QRect(0, 0, 10, 10); + QPixmap pix; + m_tester->onDocPageSliceImageTaskFinished(task, pix); + EXPECT_TRUE(g_funcName == "handleRenderFinished_stub"); +} + +// Tests onDocPageBigImageTaskFinished when sheet exists; forwards to +// BrowserPage::handleRenderFinished (stubbed). +TEST_F(TestPageRenderThread, UT_PageRenderThread_onDocPageBigImageTaskFinished_002) +{ + Stub s; + s.set(ADDR(DocSheet, existSheet), existSheet_true_stub); + s.set(ADDR(BrowserPage, handleRenderFinished), handleRenderFinished_stub); + + DocPageBigImageTask task; + task.sheet = nullptr; + task.page = nullptr; + task.pixmapId = 3; + QPixmap pix; + m_tester->onDocPageBigImageTaskFinished(task, pix); + EXPECT_TRUE(g_funcName == "handleRenderFinished_stub"); +} + +// Tests onDocPageWordTaskFinished when sheet exists; forwards to +// BrowserPage::handleWordLoaded (stubbed). +TEST_F(TestPageRenderThread, UT_PageRenderThread_onDocPageWordTaskFinished_002) +{ + Stub s; + s.set(ADDR(DocSheet, existSheet), existSheet_true_stub); + s.set(ADDR(BrowserPage, handleWordLoaded), handleWordLoaded_stub); + + DocPageWordTask task; + task.sheet = nullptr; + task.page = nullptr; + QList words; + m_tester->onDocPageWordTaskFinished(task, words); + EXPECT_TRUE(g_funcName == "handleWordLoaded_stub"); +} + +// Tests onDocPageAnnotationTaskFinished when sheet exists; forwards to +// BrowserPage::handleAnnotationLoaded (stubbed). +TEST_F(TestPageRenderThread, UT_PageRenderThread_onDocPageAnnotationTaskFinished_002) +{ + Stub s; + s.set(ADDR(DocSheet, existSheet), existSheet_true_stub); + s.set(ADDR(BrowserPage, handleAnnotationLoaded), handleAnnotationLoaded_stub); + + DocPageAnnotationTask task; + task.sheet = nullptr; + task.page = nullptr; + QList annots; + m_tester->onDocPageAnnotationTaskFinished(task, annots); + EXPECT_TRUE(g_funcName == "handleAnnotationLoaded_stub"); +} + +// Tests onDocPageThumbnailTask when sheet exists; forwards to +// SideBarImageViewModel::handleRenderThumbnail (stubbed). +TEST_F(TestPageRenderThread, UT_PageRenderThread_onDocPageThumbnailTask_002) +{ + Stub s; + s.set(ADDR(DocSheet, existSheet), existSheet_true_stub); + s.set(ADDR(SideBarImageViewModel, handleRenderThumbnail), handleRenderThumbnail_stub); + + DocPageThumbnailTask task; + task.sheet = nullptr; + task.model = nullptr; + task.index = 5; + QPixmap pix; + m_tester->onDocPageThumbnailTask(task, pix); + EXPECT_TRUE(g_funcName == "handleRenderThumbnail_stub"); +} + +// Tests onDocOpenTask when sheet exists; forwards to +// SheetRenderer::handleOpened (stubbed). +TEST_F(TestPageRenderThread, UT_PageRenderThread_onDocOpenTask_002) +{ + Stub s; + s.set(ADDR(DocSheet, existSheet), existSheet_true_stub); + s.set(ADDR(SheetRenderer, handleOpened), handleOpened_stub); + + DocOpenTask task; + task.sheet = nullptr; + task.renderer = nullptr; + QList pages; + m_tester->onDocOpenTask(task, deepin_reader::Document::NoError, nullptr, pages); + EXPECT_TRUE(g_funcName == "handleOpened_stub"); +} + +//====================================================================== +// appendTask overloads (static). Thread start is stubbed to keep the +// queued tasks from running during the test. +//====================================================================== + +// Tests appendTask(DocPageNormalImageTask). +TEST_F(TestPageRenderThread, UT_PageRenderThread_appendTask_NormalImage) +{ + Stub s; + s.set(ADDR(QThread, start), start_stub); + + DocPageNormalImageTask task; + task.sheet = nullptr; + task.page = nullptr; + PageRenderThread::appendTask(task); + EXPECT_FALSE(m_tester->m_pageNormalImageTasks.isEmpty()); + m_tester->m_pageNormalImageTasks.clear(); +} + +// Tests appendTask(DocPageSliceImageTask). +TEST_F(TestPageRenderThread, UT_PageRenderThread_appendTask_SliceImage) +{ + Stub s; + s.set(ADDR(QThread, start), start_stub); + + DocPageSliceImageTask task; + task.sheet = nullptr; + task.page = nullptr; + PageRenderThread::appendTask(task); + EXPECT_FALSE(m_tester->m_pageSliceImageTasks.isEmpty()); + m_tester->m_pageSliceImageTasks.clear(); +} + +// Tests appendTask(DocPageBigImageTask). +TEST_F(TestPageRenderThread, UT_PageRenderThread_appendTask_BigImage) +{ + Stub s; + s.set(ADDR(QThread, start), start_stub); + + DocPageBigImageTask task; + task.sheet = nullptr; + task.page = nullptr; + PageRenderThread::appendTask(task); + EXPECT_FALSE(m_tester->m_pageBigImageTasks.isEmpty()); + m_tester->m_pageBigImageTasks.clear(); +} + +// Tests appendTask(DocPageWordTask). +TEST_F(TestPageRenderThread, UT_PageRenderThread_appendTask_Word) +{ + Stub s; + s.set(ADDR(QThread, start), start_stub); + + DocPageWordTask task; + task.sheet = nullptr; + task.page = nullptr; + PageRenderThread::appendTask(task); + EXPECT_FALSE(m_tester->m_pageWordTasks.isEmpty()); + m_tester->m_pageWordTasks.clear(); +} + +// Tests appendTask(DocPageAnnotationTask). +TEST_F(TestPageRenderThread, UT_PageRenderThread_appendTask_Annotation) +{ + Stub s; + s.set(ADDR(QThread, start), start_stub); + + DocPageAnnotationTask task; + task.sheet = nullptr; + task.page = nullptr; + PageRenderThread::appendTask(task); + EXPECT_FALSE(m_tester->m_pageAnnotationTasks.isEmpty()); + m_tester->m_pageAnnotationTasks.clear(); +} + +// Tests appendTask(DocPageThumbnailTask). +TEST_F(TestPageRenderThread, UT_PageRenderThread_appendTask_Thumbnail) +{ + Stub s; + s.set(ADDR(QThread, start), start_stub); + + DocPageThumbnailTask task; + task.sheet = nullptr; + task.model = nullptr; + task.index = 0; + PageRenderThread::appendTask(task); + EXPECT_FALSE(m_tester->m_pageThumbnailTasks.isEmpty()); + m_tester->m_pageThumbnailTasks.clear(); +} + +// Tests appendTask(DocOpenTask). +TEST_F(TestPageRenderThread, UT_PageRenderThread_appendTask_Open) +{ + Stub s; + s.set(ADDR(QThread, start), start_stub); + + DocOpenTask task; + task.sheet = nullptr; + task.renderer = nullptr; + PageRenderThread::appendTask(task); + EXPECT_FALSE(m_tester->m_openTasks.isEmpty()); + m_tester->m_openTasks.clear(); +} + +// Tests appendTask(DocCloseTask). +TEST_F(TestPageRenderThread, UT_PageRenderThread_appendTask_Close) +{ + Stub s; + s.set(ADDR(QThread, start), start_stub); + + DocCloseTask task; + task.document = nullptr; + PageRenderThread::appendTask(task); + EXPECT_FALSE(m_tester->m_closeTasks.isEmpty()); + m_tester->m_closeTasks.clear(); +} + +// (NullInstance test removed: modifying s_quitForever corrupts global state +// and causes segfaults in subsequent DocSheet destructor tests.) diff --git a/tests/browser/ut_sheetbrowser.cpp b/tests/browser/ut_sheetbrowser.cpp index 254c1bc6..60dc4193 100644 --- a/tests/browser/ut_sheetbrowser.cpp +++ b/tests/browser/ut_sheetbrowser.cpp @@ -15,6 +15,7 @@ #include "dpdfpage.h" #include "TipsWidget.h" #include "TextEditWidget.h" +#include "Utils.h" #include "stub.h" #include @@ -23,6 +24,8 @@ #include #include #include +#include +#include #include #include "ut_compat.h" @@ -2498,3 +2501,150 @@ TEST_F(TestSheetBrowser, testfirstThumbnail001) EXPECT_FALSE(m_tester->firstThumbnail(strPath).isNull()); } + +TEST_F(TestSheetBrowser, testshowEvent_ext) +{ + QShowEvent event; + m_tester->showEvent(&event); + EXPECT_TRUE(m_tester->m_items.count() == 2); +} + +TEST_F(TestSheetBrowser, testsizeModeChanged_ext) +{ + Stub s; + s.set(ADDR(FindWidget, updatePosition), showPosition_stub); + DocSheet *sheet = new DocSheet(Dr::FileType::PDF, "1.pdf", nullptr); + sheet->m_fileType = Dr::FileType::PDF; + m_tester->m_sheet = sheet; + + m_tester->handlePrepareSearch(); + emit DGuiApplicationHelper::instance()->sizeModeChanged(DGuiApplicationHelper::CompactMode); + emit DGuiApplicationHelper::instance()->sizeModeChanged(DGuiApplicationHelper::NormalMode); + + delete sheet; + SUCCEED(); +} + +TEST_F(TestSheetBrowser, testtimerEvent_repeatTimer) +{ + // Cover SheetBrowser::timerEvent() branch where the timer id + // matches m_repeatTimer.timerId(). + m_tester->m_repeatTimer.start(5000, m_tester); + int tid = m_tester->m_repeatTimer.timerId(); + ASSERT_GT(tid, 0); + + QTimerEvent event(tid); + m_tester->timerEvent(&event); + + EXPECT_FALSE(m_tester->m_canTouchScreen); + EXPECT_FALSE(m_tester->m_repeatTimer.isActive()); +} + +TEST_F(TestSheetBrowser, testtimerEvent_other) +{ + // Cover SheetBrowser::timerEvent() branch where the timer id + // does NOT match m_repeatTimer.timerId(). + m_tester->m_canTouchScreen = true; + QTimerEvent event(999999); // unlikely to collide + m_tester->timerEvent(&event); + EXPECT_TRUE(m_tester->m_canTouchScreen); +} + +TEST_F(TestSheetBrowser, testshowNoteEditWidget_sigHideLambda) +{ + // Cover the sigHide lambda inside SheetBrowser::showNoteEditWidget(). + Stub s; + s.set(ADDR(TextEditShadowWidget, showWidget), showWidget_stub); + s.set(ADDR(SheetBrowser, setIconAnnotSelect), show_stub); + + DPdfTextAnnot *dPdfAnnot = new DPdfTextAnnot(); + Annotation *annotation = new PDFAnnotation(dPdfAnnot); + QPoint point(0, 0); + + m_tester->m_bHandAndLink = false; + g_funcName.clear(); + m_tester->showNoteEditWidget(annotation, point); + ASSERT_NE(m_tester->m_noteEditWidget, nullptr); + + // Emitting sigHide should invoke the connected lambda, which calls + // setIconAnnotSelect(false). + emit m_tester->m_noteEditWidget->getTextEditWidget()->sigHide(); + + EXPECT_TRUE(g_funcName == "show_stub"); + + delete dPdfAnnot; + delete annotation; +} + +// Stub for QMenu::exec that emits signalMenuItemClicked while showMenu() +// is still running. This lets us invoke the local lambda that is registered +// inside SheetBrowser::showMenu() and SheetBrowser::mousePressEvent(). +typedef QAction *(*CapturedExecSig)(QMenu *, const QPoint &, QAction *); +QAction *exec_emitCopy_stub(QMenu *self, const QPoint &pos, QAction *at) +{ + Q_UNUSED(pos) + Q_UNUSED(at) + BrowserMenu *menu = static_cast(self); + emit menu->signalMenuItemClicked("Copy"); + return nullptr; +} + +TEST_F(TestSheetBrowser, testshowMenu_lambda) +{ + // Cover the signalMenuItemClicked lambda inside SheetBrowser::showMenu(). + Stub stub; + stub.set(ADDR(SheetBrowser, selectedWordsText), selectedWordsText_stub); + stub.set(ADDR(BrowserMenu, initActions), initActions_stub); + stub.set((QAction * (QMenu::*)(const QPoint &, QAction *))ADDR(QMenu, exec), exec_emitCopy_stub); + stub.set(ADDR(SheetBrowser, clearSelectIconAnnotAfterMenu), clearSelectIconAnnotAfterMenu_stub); + stub.set(ADDR(Utils, copyText), show_stub); + + DocSheet *sheet = new DocSheet(Dr::FileType::PDF, "1.pdf", nullptr); + m_tester->m_sheet = sheet; + + BrowserWord *p = new BrowserWord(nullptr, Word()); + m_tester->m_selectEndWord = p; + + g_funcName.clear(); + m_tester->showMenu(); + EXPECT_TRUE(g_funcName == "show_stub"); + + delete p; + delete sheet; +} + +// items() stub that returns a list containing a BrowserPage, so mousePressEvent +// finds a non-null item and proceeds to create the context menu. +static QList items_stub_browserpage(const QPointF &, Qt::ItemSelectionMode, Qt::SortOrder, const QTransform &) +{ + QList items; + DocSheet sheet(Dr::FileType::PDF, "1.pdf", nullptr); + items.append(new BrowserPage(nullptr, 0, &sheet)); + return items; +} + +TEST_F(TestSheetBrowser, testmousePressEvent_lambda) +{ + // Cover the signalMenuItemClicked lambda inside SheetBrowser::mousePressEvent(). + Stub stub; + stub.set(ADDR(SheetBrowser, selectedWordsText), selectedWordsText_stub); + stub.set(ADDR(BrowserMenu, initActions), initActions_stub); + stub.set((QAction * (QMenu::*)(const QPoint &, QAction *))ADDR(QMenu, exec), exec_emitCopy_stub); + stub.set(static_cast(QGraphicsScene::*)(const QPointF &, Qt::ItemSelectionMode, Qt::SortOrder, const QTransform &) const>(ADDR(QGraphicsScene, items)), items_stub_browserpage); + stub.set(ADDR(Utils, copyText), show_stub); + + DocSheet *sheet = new DocSheet(Dr::FileType::PDF, "1.pdf", nullptr); + m_tester->m_sheet = sheet; + + QPointF localPos(10, 10); + QMouseEvent *event = createMouseEvent(QEvent::MouseButtonPress, localPos, Qt::RightButton, Qt::RightButton, Qt::NoModifier); + + g_funcName.clear(); + m_tester->mousePressEvent(event); + EXPECT_TRUE(g_funcName == "show_stub"); + + delete event; + delete sheet; + qDeleteAll(g_QGraphicsItemList); + g_QGraphicsItemList.clear(); +}