Skip to content

Commit 6019a7d

Browse files
committed
Update tests
1 parent c956ba2 commit 6019a7d

38 files changed

Lines changed: 6827 additions & 156 deletions

Source/Canvas.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1590,8 +1590,12 @@ void Canvas::deselectAll(bool const broadcastChange)
15901590
s->hideParameters();
15911591

15921592
if (!broadcastChange) {
1593-
// Add back the listener, but make sure it's added back 'after' the last event on the message queue
1594-
MessageManager::callAsync([this] { selectedComponents.addChangeListener(this); });
1593+
// Add back the listener, but make sure it's added back 'after' the last event on the message queue.
1594+
// Guard with a SafePointer: the canvas may be deleted (e.g. its tab closed) before this runs.
1595+
MessageManager::callAsync([_this = SafePointer(this)] {
1596+
if (_this)
1597+
_this->selectedComponents.addChangeListener(_this);
1598+
});
15951599
}
15961600
}
15971601

@@ -2559,8 +2563,12 @@ void Canvas::setSelected(Component* component, bool const shouldNowBeSelected, b
25592563
}
25602564

25612565
if (!broadcastChange) {
2562-
// Add back the listener, but make sure it's added back 'after' the last event on the message queue
2563-
MessageManager::callAsync([this] { selectedComponents.addChangeListener(this); });
2566+
// Add back the listener, but make sure it's added back 'after' the last event on the message queue.
2567+
// Guard with a SafePointer: the canvas may be deleted (e.g. its tab closed) before this runs.
2568+
MessageManager::callAsync([_this = SafePointer(this)] {
2569+
if (_this)
2570+
_this->selectedComponents.addChangeListener(_this);
2571+
});
25642572
}
25652573
}
25662574

Source/Components/MarkupDisplay.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -630,10 +630,10 @@ class TableBlock final : public Block {
630630
for (int i = 0; i < table.cells.size(); i++) {
631631
OwnedArray<Table::Cell> const* row = table.cells[i];
632632
for (int j = 0; j < row->size(); j++) {
633-
if (j < table.columnwidths.size()) {
633+
if (j < static_cast<int>(table.columnwidths.size())) {
634634
table.columnwidths[j] = jmax(table.columnwidths[j], (*row)[j]->width);
635635
} else {
636-
table.columnwidths[j] = (*row)[j]->width;
636+
table.columnwidths.add((*row)[j]->width);
637637
}
638638
}
639639
}
@@ -645,7 +645,7 @@ class TableBlock final : public Block {
645645
for (int j = 0; j < row->size(); j++) {
646646
rowheight = jmax(rowheight, (*row)[j]->height);
647647
}
648-
table.rowheights[i] = rowheight;
648+
table.rowheights.add(rowheight);
649649
}
650650
table.setBounds(0, 0, getWidthRequired() + table.leftmargin + table.cellgap, getHeightRequired(0.f));
651651
}

Source/Dialogs/Deken.h

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,13 @@ class PackageManager final : public Thread
9696
.withConnectionTimeoutMs(10000)
9797
.withStatusCode(&statusCode));
9898

99-
if (instream != nullptr && statusCode == 200) {
99+
bool downloadOk = instream != nullptr && statusCode == 200;
100+
#if ENABLE_TESTING
101+
// Local file:// archives used by the test suite don't report an
102+
// HTTP status, so accept any readable stream while testing
103+
downloadOk = instream != nullptr;
104+
#endif
105+
if (downloadOk) {
100106
startThread();
101107
} else {
102108
finish(Result::fail("Failed to start download"));
@@ -228,24 +234,37 @@ class PackageManager final : public Thread
228234

229235
PackageList getAvailablePackages()
230236
{
237+
MemoryBlock block;
231238

232-
// plugdata's deken servers, hosted on GitHub
233-
// This will pre-parse the deken repo information to a faster and smaller format
234-
// This saves a lot of work that plugdata would have to do on startup!
235-
236-
auto const triplet = os + "-" + machine + "-" + floatsize;
237-
auto const repoForArchitecture = "https://raw.githubusercontent.com/plugdata-team/plugdata-deken/main/bin/" + triplet + ".bin";
238-
239-
webstream = std::make_unique<WebInputStream>(URL(repoForArchitecture), false);
240-
webstream->connect(nullptr);
241-
242-
if (webstream->isError()) {
239+
#if ENABLE_TESTING
240+
// The test suite injects a serialised package tree (or forces a failure)
241+
// here, so no network request is made during testing
242+
if (mockShouldFail) {
243243
sendActionMessage("Failed to connect to server");
244244
return { };
245245
}
246+
if (mockPackageData.getSize() > 0) {
247+
block = mockPackageData;
248+
} else
249+
#endif
250+
{
251+
// plugdata's deken servers, hosted on GitHub
252+
// This will pre-parse the deken repo information to a faster and smaller format
253+
// This saves a lot of work that plugdata would have to do on startup!
246254

247-
MemoryBlock block;
248-
webstream->readIntoMemoryBlock(block);
255+
auto const triplet = os + "-" + machine + "-" + floatsize;
256+
auto const repoForArchitecture = "https://raw.githubusercontent.com/plugdata-team/plugdata-deken/main/bin/" + triplet + ".bin";
257+
258+
webstream = std::make_unique<WebInputStream>(URL(repoForArchitecture), false);
259+
webstream->connect(nullptr);
260+
261+
if (webstream->isError()) {
262+
sendActionMessage("Failed to connect to server");
263+
return { };
264+
}
265+
266+
webstream->readIntoMemoryBlock(block);
267+
}
249268

250269
// Parse tree that was downloaded
251270
auto const tree = ValueTree::readFromData(block.getData(), block.getSize());
@@ -345,7 +364,15 @@ class PackageManager final : public Thread
345364

346365
PackageList allPackages;
347366

367+
#if ENABLE_TESTING
368+
// The test suite installs into a temp dir and injects mock catalog data,
369+
// so neither the network nor the user's real Externals folder is touched
370+
static inline File filesystem = ProjectInfo::appDataDir.getChildFile("Externals");
371+
static inline MemoryBlock mockPackageData;
372+
static inline bool mockShouldFail = false;
373+
#else
348374
static inline File const filesystem = ProjectInfo::appDataDir.getChildFile("Externals");
375+
#endif
349376

350377
// Package info file
351378
File pkgInfo = filesystem.getChildFile(".pkg_info");
@@ -409,7 +436,9 @@ class PackageManager final : public Thread
409436
JUCE_DECLARE_SINGLETON(PackageManager, false)
410437
};
411438

439+
#ifndef PLUGDATA_TEST_TRANSLATION_UNIT // implemented in Dialogs.cpp's TU
412440
JUCE_IMPLEMENT_SINGLETON(PackageManager)
441+
#endif
413442

414443
class Deken final : public Component
415444
, public ListBoxModel

Source/Dialogs/Dialogs.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,6 +937,9 @@ void Dialogs::dismissFileDialog()
937937

938938
void Dialogs::showOpenDialog(std::function<void(URL)> const& callback, bool const canSelectFiles, bool const canSelectDirectories, String const& extension, String const& lastFileId, Component* parentComponent)
939939
{
940+
#if ENABLE_TESTING
941+
return; // Don't open file dialogs during testing
942+
#endif
940943
bool nativeDialog = SettingsFile::getInstance()->wantsNativeDialog();
941944
auto initialFile = lastFileId.isNotEmpty() ? SettingsFile::getInstance()->getLastBrowserPathForId(lastFileId) : ProjectInfo::appDataDir;
942945
if (!initialFile.exists())
@@ -980,6 +983,9 @@ void Dialogs::showOpenDialog(std::function<void(URL)> const& callback, bool cons
980983

981984
void Dialogs::showSaveDialog(std::function<void(URL)> const& callback, String const& extension, String const& lastFileId, Component* parentComponent, bool const directoryMode, String const& defaultFileName)
982985
{
986+
#if ENABLE_TESTING
987+
return; // Don't open file dialogs during testing
988+
#endif
983989
bool nativeDialog = SettingsFile::getInstance()->wantsNativeDialog();
984990
auto initialFile = lastFileId.isNotEmpty() ? SettingsFile::getInstance()->getLastBrowserPathForId(lastFileId) : ProjectInfo::appDataDir;
985991
if (!initialFile.exists())

Source/Dialogs/PatchStore.h

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,29 +47,49 @@ class DownloadPool final : public DeletedAtShutdown {
4747
cancelImageDownloads();
4848
imagePool.addJob([this] {
4949
SmallArray<PatchInfo> patches;
50-
int statusCode = 0;
51-
auto const webstream = URL("https://plugdata.org/store.json").createInputStream(URL::InputStreamOptions(URL::ParameterHandling::inAddress).withConnectionTimeoutMs(10000).withStatusCode(&statusCode));
5250

53-
if (!webstream || statusCode >= 400) {
51+
String jsonString;
52+
#if ENABLE_TESTING
53+
// The test suite injects mock catalog JSON (or forces a failure)
54+
// here, so no network request is made during testing
55+
if (mockStoreShouldFail) {
5456
MessageManager::callAsync([this] {
5557
for (auto& listener : listeners) {
5658
listener->databaseDownloadFailed();
5759
}
5860
});
5961
return;
6062
}
63+
if (mockStoreJson.isNotEmpty()) {
64+
jsonString = mockStoreJson;
65+
} else
66+
#endif
67+
{
68+
int statusCode = 0;
69+
auto const webstream = URL("https://plugdata.org/store.json").createInputStream(URL::InputStreamOptions(URL::ParameterHandling::inAddress).withConnectionTimeoutMs(10000).withStatusCode(&statusCode));
6170

62-
MemoryBlock jsonData;
63-
MemoryOutputStream mo(jsonData, false);
71+
if (!webstream || statusCode >= 400) {
72+
MessageManager::callAsync([this] {
73+
for (auto& listener : listeners) {
74+
listener->databaseDownloadFailed();
75+
}
76+
});
77+
return;
78+
}
6479

65-
mo.preallocate(32000); // fit store.json file with some extra space
66-
while (true) {
67-
auto const written = mo.writeFromInputStream(*webstream, 1 << 14);
68-
if (written == 0)
69-
break;
80+
MemoryBlock jsonData;
81+
MemoryOutputStream mo(jsonData, false);
82+
83+
mo.preallocate(32000); // fit store.json file with some extra space
84+
while (true) {
85+
auto const written = mo.writeFromInputStream(*webstream, 1 << 14);
86+
if (written == 0)
87+
break;
88+
}
89+
jsonString = jsonData.toString(); // Converting to string is important on Windows to get correct character encoding
7090
}
7191

72-
auto const parsedData = JSON::parse(jsonData.toString()); // Converting to string is important on Windows to get correct character encoding
92+
auto const parsedData = JSON::parse(jsonString);
7393
auto patchData = parsedData["Patches"];
7494
if (patchData.isArray()) {
7595
for (int i = 0; i < patchData.size(); ++i) {
@@ -265,10 +285,19 @@ class DownloadPool final : public DeletedAtShutdown {
265285
std::atomic<bool> cancelledImageDownload = false;
266286

267287
public:
288+
#if ENABLE_TESTING
289+
// The test suite injects mock catalog JSON (or forces a failure) so the
290+
// store database can be exercised without any network access
291+
static inline String mockStoreJson;
292+
static inline bool mockStoreShouldFail = false;
293+
#endif
294+
268295
JUCE_DECLARE_SINGLETON(DownloadPool, false);
269296
};
270297

298+
#ifndef PLUGDATA_TEST_TRANSLATION_UNIT // implemented in Dialogs.cpp's TU
271299
JUCE_IMPLEMENT_SINGLETON(DownloadPool);
300+
#endif
272301

273302
class OnlineImage final : public Component
274303
, public DownloadPool::DownloadListener {

0 commit comments

Comments
 (0)