// Standalone tests for reasampler::buildFolderTree — no REAPER, no framework. // The D2 view shell is DAW-bound and only verifiable in REAPER; this covers the // one genuinely pure piece: the I_FOLDERDEPTH walk that turns REAPER's linear // track stream into the parent<->child FolderTree the pure model consumes. #include "../src/view_tree.h" #include #include using namespace reasampler; static int g_fail = 0; #define CHECK(cond) do { if(!(cond)) { \ std::printf("FAIL line %d: %s\n", __LINE__, #cond); ++g_fail; } } while(0) // Find a node by guid; returns nullptr if absent. static const FolderNode* nodeOf(const FolderTree& t, const std::string& guid) { for (const auto& n : t.nodes) if (n.guid == guid) return &n; return nullptr; } // All top-level leaves: three depth-0 tracks, no folders. Every parentGuid empty, // nothing is a parent, order preserved. static void testFlatLeaves() { FolderTree t = buildFolderTree({{"a", 0}, {"b", 0}, {"c", 0}}); CHECK(t.nodes.size() == 3); CHECK(t.nodes[0].guid == "a" && t.nodes[1].guid == "b" && t.nodes[2].guid == "c"); for (const auto& n : t.nodes) { CHECK(n.parentGuid.empty()); CHECK(!n.isParent); } } // One folder: parent P (depth 1) contains child C, which closes the folder (-1). // P is a parent and is itself top-level; C's parent is P. static void testSingleFolder() { FolderTree t = buildFolderTree({{"P", 1}, {"C", -1}}); const FolderNode* p = nodeOf(t, "P"); const FolderNode* c = nodeOf(t, "C"); CHECK(p && c); CHECK(p->isParent); CHECK(p->parentGuid.empty()); // the folder parent is itself top-level CHECK(!c->isParent); CHECK(c->parentGuid == "P"); // child sits under the folder } // Folder with two children; a following top-level leaf must land back at the root, // proving the close (-1) popped the folder off the stack. static void testFolderThenSibling() { FolderTree t = buildFolderTree({{"P", 1}, {"C1", 0}, {"C2", -1}, {"S", 0}}); CHECK(nodeOf(t, "C1")->parentGuid == "P"); CHECK(nodeOf(t, "C2")->parentGuid == "P"); CHECK(nodeOf(t, "S")->parentGuid.empty()); // popped back to root } // Nested folders: P > Q > leaf. The inner leaf closes BOTH folders at once (-2). // A sibling after it returns to the root. static void testNestedDeepClose() { FolderTree t = buildFolderTree({{"P", 1}, {"Q", 1}, {"L", -2}, {"S", 0}}); CHECK(nodeOf(t, "P")->isParent && nodeOf(t, "P")->parentGuid.empty()); CHECK(nodeOf(t, "Q")->isParent && nodeOf(t, "Q")->parentGuid == "P"); CHECK(nodeOf(t, "L")->parentGuid == "Q"); // deepest leaf under Q CHECK(!nodeOf(t, "L")->isParent); CHECK(nodeOf(t, "S")->parentGuid.empty()); // both levels popped } // Nested with a stepwise close: inner folder closes (-1), then a sibling at the // OUTER level, then that folder closes (-1). Proves partial pops track correctly. static void testNestedStepwiseClose() { FolderTree t = buildFolderTree( {{"P", 1}, {"Q", 1}, {"L", -1}, {"M", -1}}); CHECK(nodeOf(t, "Q")->parentGuid == "P"); CHECK(nodeOf(t, "L")->parentGuid == "Q"); // L inside inner folder Q CHECK(nodeOf(t, "M")->parentGuid == "P"); // after Q closed, M is under P } // Malformed stream: a close deeper than the open stack must clamp to empty, never // underflow. A following leaf is still top-level and the walk stays total. static void testMalformedCloseClamps() { FolderTree t = buildFolderTree({{"P", 1}, {"C", -5}, {"S", 0}}); CHECK(nodeOf(t, "C")->parentGuid == "P"); CHECK(nodeOf(t, "S")->parentGuid.empty()); // clamped, not underflowed CHECK(t.nodes.size() == 3); } // Empty input yields an empty tree (no fault). static void testEmpty() { FolderTree t = buildFolderTree({}); CHECK(t.nodes.empty()); } // An empty folder (parent immediately closes itself, depth accounting P=1 then a // child that both belongs to and closes it). Here P opens and the sole child // closes; verifies a folder with exactly one leaf child. static void testSingleChildFolder() { FolderTree t = buildFolderTree({{"P", 1}, {"only", -1}}); CHECK(nodeOf(t, "only")->parentGuid == "P"); CHECK(nodeOf(t, "P")->isParent); } int main() { testFlatLeaves(); testSingleFolder(); testFolderThenSibling(); testNestedDeepClose(); testNestedStepwiseClose(); testMalformedCloseClamps(); testEmpty(); testSingleChildFolder(); if (g_fail == 0) { std::printf("view_tree: all tests passed\n"); return 0; } std::printf("view_tree: %d checks FAILED\n", g_fail); return 1; }