-
-
Notifications
You must be signed in to change notification settings - Fork 387
Expand file tree
/
Copy pathTestRunner.h
More file actions
99 lines (71 loc) · 3.21 KB
/
Copy pathTestRunner.h
File metadata and controls
99 lines (71 loc) · 3.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#pragma once
#include <QHash>
#include <QList>
#include <QMap>
#include <QMutex>
#include <QPair>
#include <QString>
#include <QStringList>
#include <atomic>
#include <functional>
#include <memory>
#ifndef Q_MOC_RUN
#include <core/server/gen/libcore.pb.h>
#endif
#include "include/database/entities/Profile.h"
class MainWindow;
// Owns profile measuring: URL latency, egress IP and speed. Not a QObject: queued
// signals would reorder the synchronous progress path, and tr() would change context.
class TestRunner {
public:
explicit TestRunner(MainWindow* mw) : mw_(mw) {}
TestRunner(const TestRunner&) = delete;
TestRunner& operator=(const TestRunner&) = delete;
// `onFinished` fires on every exit path, so a caller may block on it.
void runUrlTests(const QList<int>& profileIDs, const std::function<void()>& onFinished = {});
void runIpTests(const QList<int>& profileIDs);
void runSpeedTests(const QList<int>& profileIDs, bool testCurrent = false);
void stop();
bool isRunning();
// A profile stop has to cancel the test before tearing the instance down.
bool isTestingCurrent() const { return testingCurrent_.load(); }
private:
enum class LatencyKind { Url, Ip };
struct Target {
QString coreConfig;
QString xrayConfig;
QStringList xrayFullConfigs;
QStringList outboundTags;
QMap<QString, int> tag2entID;
int entID = -1;
// Not derivable from an empty outboundTags: a test-current run leaves
// both empty but must let the core pick "proxy" over the config default.
bool useDefaultOutbound = false;
bool testCurrent = false;
};
void runLatencyGroup(LatencyKind kind, const QList<int>& requestedIDs,
const std::function<void()>& onFinished);
void runUrlProbe(const Target& target);
void runIpProbe(const Target& target);
void runSpeedProbe(const Target& target);
// Shared by the live progress poll and the final pass, which must not drift.
void applyUrlResult(const std::shared_ptr<Configs::Profile>& ent, const libcore::URLTestResp& res);
void applyIpResult(const std::shared_ptr<Configs::Profile>& ent, const libcore::IPTestRes& res);
QString contextName(int entID) const;
// `gen` is the sweep the poll belongs to, re-checked once the query returns.
void pollSpeedTest(const QMap<QString, int>& tag2entID, bool testCurrent, quint64 gen);
void pollCountryTest(const QMap<QString, int>& tag2entID, bool testCurrent, quint64 gen);
void creditTraffic(const std::shared_ptr<Configs::Profile>& profile, const QString& tag,
qint64 curUp, qint64 curDown);
MainWindow* mw_;
// Held for a whole sweep, so it must never double as a per-batch latch.
QMutex session_;
// A poll thread is not joined, so a late tick must not drain the next sweep.
std::atomic<quint64> sessionGen_ = 0;
std::atomic<bool> stopRequested_ = false;
std::atomic<bool> testingCurrent_ = false;
// Tests dial the outbound directly and bypass the clash tracker, so their
// bytes are counted only here, diffed per tag against the last report.
QMutex creditMu_;
QHash<QString, QPair<qint64, qint64>> credited_;
};