aboutsummaryrefslogtreecommitdiff
path: root/tests/unit/libutil/closure.cc
blob: 7597e78073b4a05a48fde155dc3b952d2e97e974 (plain)
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
#include "closure.hh"
#include <gtest/gtest.h>

namespace nix {

using namespace std;

map<string, set<string>> testGraph = {
    { "A", { "B", "C", "G" } },
    { "B", { "A" } }, // Loops back to A
    { "C", { "F" } }, // Indirect reference
    { "D", { "A" } }, // Not reachable, but has backreferences
    { "E", {} }, // Just not reachable
    { "F", {} },
    { "G", { "G" } }, // Self reference
};

TEST(closure, correctClosure) {
    set<string> aClosure;
    set<string> expectedClosure = {"A", "B", "C", "F", "G"};
    computeClosure<string>(
        {"A"},
        aClosure,
        [&](const string currentNode, function<void(promise<set<string>> &)> processEdges) {
            promise<set<string>> promisedNodes;
            promisedNodes.set_value(testGraph[currentNode]);
            processEdges(promisedNodes);
        }
    );

    ASSERT_EQ(aClosure, expectedClosure);
}

TEST(closure, properlyHandlesDirectExceptions) {
    struct TestExn {};
    set<string> aClosure;
    EXPECT_THROW(
        computeClosure<string>(
            {"A"},
            aClosure,
            [&](const string currentNode, function<void(promise<set<string>> &)> processEdges) {
                throw TestExn();
            }
        ),
        TestExn
    );
}

TEST(closure, properlyHandlesExceptionsInPromise) {
    struct TestExn {};
    set<string> aClosure;
    EXPECT_THROW(
        computeClosure<string>(
            {"A"},
            aClosure,
            [&](const string currentNode, function<void(promise<set<string>> &)> processEdges) {
                promise<set<string>> promise;
                try {
                    throw TestExn();
                } catch (...) {
                    promise.set_exception(std::current_exception());
                }
                processEdges(promise);
            }
        ),
        TestExn
    );
}

}