MailJDTourDownloadDocsQualityTestsCoverage

Which source lines and branches the tests execute. Lines 91.5 %, branches 75.0 % (minimum 85 % and 72 %). main @ 399ffe3d · 21 October 2026 · pipeline 7238.

GCC Code Coverage Report


Directory: src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 0.0% 0 / 0 / 1
Functions: 0.0% 0 / 0 / 1
Branches: 0.0% 0 / 0 / 2

service/FolderPredictionService.h
Line Branch Exec Source
1 #pragma once
2
3 #include "data/FolderEvidenceModel.h"
4 #include "data/FolderPredictor.h"
5 #include "data/FolderSuggestion.h"
6 #include "data/MailRequest.h"
7 #include <QHash>
8 #include <QObject>
9 #include <QPointer>
10 #include <QStringList>
11 #include <QThreadPool>
12 #include <atomic>
13 #include <functional>
14 #include <memory>
15 #include <optional>
16
17 struct FolderPredictionRequest {
18 QString cachePath, predictorPath, account, folder, junkFolder;
19 qint64 folderId = -1;
20 quint32 uidValidity = 0;
21 QList<qint64> uids;
22 };
23
24 struct FolderPredictionResult {
25 struct Item { MailId mailId; FolderSuggestion suggestion; };
26 QList<Item> items;
27 QString error;
28 quint32 uidValidity = 0;
29 // S105.3.5: answered from the stored suggestions while the evidence
30 // model is still being built; evidenceRebuilt() follows.
31 bool provisional = false;
32 };
33
34 // Shared derived reads. Only bounded mailbox identities are queued; envelopes
35 // and classifier connections live on one worker, never on the scene thread.
36 // Latest demand replaces an owner's old request, including completed results
37 // not yet delivered. Consumers must still fence their current session/epoch.
38 // Sprint 105 S105.3.5/S105.3.7: the suggestions come from one in-memory
39 // FolderEvidenceModel per account and cache file, built on the worker from
40 // the filed mails (and learning new filings per batch); every computed
41 // suggestion is stored, so a restart answers from the store first.
42 class FolderPredictionService : public QObject {
43 Q_OBJECT
44 public:
45 using Callback = std::function<void(FolderPredictionResult)>;
46 static constexpr int MaxPending = 8;
47 static constexpr int MaxRows = 128;
48 explicit FolderPredictionService(QObject *parent = nullptr);
49 ~FolderPredictionService() override;
50 static FolderPredictionService *shared();
51 void predict(QObject *owner, FolderPredictionRequest input, Callback callback);
52 void cancel(QObject *owner);
53 // Queued requests; background demand (arrivals) leaves room for the list.
54 ✗ int pendingCount() const { return int(m_pending.size()) + (m_active ? 1 : 0); }
55 // S105.3.3: the user filed this mail into `folder` (a move); counts at
56 // once, before the moved row reaches the cache.
57 void recordFiling(const QString &cachePath, const QString &account, const MailHeader &header, const QString &folder);
58 // A folder was renamed or removed: the account's model is rebuilt.
59 void forgetAccount(const QString &account);
60
61 signals:
62 // The evidence model of `account` was (re)built; suggestions delivered
63 // before (provisional or from the old model) may differ now.
64 void evidenceRebuilt(const QString &account);
65
66 private:
67 friend class TestFolderPrediction;
68 struct Request {
69 QPointer<QObject> owner;
70 FolderPredictionRequest input;
71 Callback callback;
72 std::shared_ptr<std::atomic_bool> cancelled = std::make_shared<std::atomic_bool>(false);
73 QMetaObject::Connection destroyed;
74 };
75 struct Warm {
76 QString cachePath, account;
77 };
78 void startNext();
79 void startWarm();
80 void stop();
81 std::shared_ptr<FolderEvidenceModel> modelFor(const QString &cachePath, const QString &account);
82 static FolderPredictionResult classify(const FolderPredictionRequest &input, const std::atomic_bool &cancelled,
83 const std::shared_ptr<FolderPredictor::StatisticsCache> &statistics,
84 FolderEvidenceModel &model);
85 bool m_stopping = false;
86 QThreadPool m_pool;
87 QList<Request> m_pending;
88 std::optional<Request> m_active;
89 QList<Warm> m_warm;
90 bool m_warming = false;
91 QHash<QString, std::shared_ptr<FolderEvidenceModel>> m_models; // cachePath + '\n' + account
92 // F100-50: the model statistics survive between batches until the
93 // predictor database reports a new statistics revision.
94 std::shared_ptr<FolderPredictor::StatisticsCache> m_statistics = std::make_shared<FolderPredictor::StatisticsCache>();
95 };
96