blob: b3ab4bdfcad8e88bb3ea442f40ab8b5f7ed739d6 [file] [log] [blame]
robertphillips423f6462015-10-19 12:15:55 -07001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/utils/SkRandom.h"
Robert Phillipsfbbc3bb2020-11-16 14:58:56 -05009#include "src/gpu/GrTTopoSort.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "tests/Test.h"
robertphillips423f6462015-10-19 12:15:55 -070011
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "tools/ToolUtils.h"
robertphillips423f6462015-10-19 12:15:55 -070013
Mike Kleinea3f0142019-03-20 11:12:10 -050014typedef void (*CreateGraphPF)(SkTArray<sk_sp<ToolUtils::TopoTestNode>>* graph);
robertphillips423f6462015-10-19 12:15:55 -070015
16/* Simple diamond
17 * 3
Robert Phillipsa186c352020-11-17 13:22:05 -050018 * . .
robertphillips423f6462015-10-19 12:15:55 -070019 * / \
20 * 1 2
Robert Phillipsa186c352020-11-17 13:22:05 -050021 * . .
robertphillips423f6462015-10-19 12:15:55 -070022 * \ /
23 * 0
24 */
Mike Kleinea3f0142019-03-20 11:12:10 -050025static void create_graph0(SkTArray<sk_sp<ToolUtils::TopoTestNode>>* graph) {
26 ToolUtils::TopoTestNode::AllocNodes(graph, 4);
robertphillips423f6462015-10-19 12:15:55 -070027
Robert Phillips4150eea2018-02-07 17:08:21 -050028 (*graph)[0]->dependsOn((*graph)[1].get());
29 (*graph)[0]->dependsOn((*graph)[2].get());
30 (*graph)[1]->dependsOn((*graph)[3].get());
31 (*graph)[2]->dependsOn((*graph)[3].get());
robertphillips423f6462015-10-19 12:15:55 -070032}
33
34/* Simple chain
35 * 3
Robert Phillipsa186c352020-11-17 13:22:05 -050036 * ^
robertphillips423f6462015-10-19 12:15:55 -070037 * |
38 * 2
Robert Phillipsa186c352020-11-17 13:22:05 -050039 * ^
robertphillips423f6462015-10-19 12:15:55 -070040 * |
41 * 1
Robert Phillipsa186c352020-11-17 13:22:05 -050042 * ^
robertphillips423f6462015-10-19 12:15:55 -070043 * |
44 * 0
45 */
Mike Kleinea3f0142019-03-20 11:12:10 -050046static void create_graph1(SkTArray<sk_sp<ToolUtils::TopoTestNode>>* graph) {
47 ToolUtils::TopoTestNode::AllocNodes(graph, 4);
robertphillips423f6462015-10-19 12:15:55 -070048
Robert Phillips4150eea2018-02-07 17:08:21 -050049 (*graph)[0]->dependsOn((*graph)[1].get());
50 (*graph)[1]->dependsOn((*graph)[2].get());
51 (*graph)[2]->dependsOn((*graph)[3].get());
robertphillips423f6462015-10-19 12:15:55 -070052}
53
Robert Phillipsa186c352020-11-17 13:22:05 -050054/* Simple Loop
robertphillips423f6462015-10-19 12:15:55 -070055 * 2
Robert Phillipsa186c352020-11-17 13:22:05 -050056 * / .
robertphillips423f6462015-10-19 12:15:55 -070057 * / \
Robert Phillipsa186c352020-11-17 13:22:05 -050058 * . \
59 * 0 ---> 1
robertphillips423f6462015-10-19 12:15:55 -070060 */
Mike Kleinea3f0142019-03-20 11:12:10 -050061static void create_graph2(SkTArray<sk_sp<ToolUtils::TopoTestNode>>* graph) {
62 ToolUtils::TopoTestNode::AllocNodes(graph, 3);
robertphillips423f6462015-10-19 12:15:55 -070063
Robert Phillips4150eea2018-02-07 17:08:21 -050064 (*graph)[0]->dependsOn((*graph)[1].get());
65 (*graph)[1]->dependsOn((*graph)[2].get());
66 (*graph)[2]->dependsOn((*graph)[0].get());
robertphillips423f6462015-10-19 12:15:55 -070067}
68
69/* Double diamond
70 * 6
Robert Phillipsa186c352020-11-17 13:22:05 -050071 * . .
robertphillips423f6462015-10-19 12:15:55 -070072 * / \
73 * 4 5
Robert Phillipsa186c352020-11-17 13:22:05 -050074 * . .
robertphillips423f6462015-10-19 12:15:55 -070075 * \ /
76 * 3
Robert Phillipsa186c352020-11-17 13:22:05 -050077 * . .
robertphillips423f6462015-10-19 12:15:55 -070078 * / \
79 * 1 2
Robert Phillipsa186c352020-11-17 13:22:05 -050080 * . .
robertphillips423f6462015-10-19 12:15:55 -070081 * \ /
82 * 0
83 */
Mike Kleinea3f0142019-03-20 11:12:10 -050084static void create_graph3(SkTArray<sk_sp<ToolUtils::TopoTestNode>>* graph) {
85 ToolUtils::TopoTestNode::AllocNodes(graph, 7);
robertphillips423f6462015-10-19 12:15:55 -070086
Robert Phillips4150eea2018-02-07 17:08:21 -050087 (*graph)[0]->dependsOn((*graph)[1].get());
88 (*graph)[0]->dependsOn((*graph)[2].get());
89 (*graph)[1]->dependsOn((*graph)[3].get());
90 (*graph)[2]->dependsOn((*graph)[3].get());
robertphillips423f6462015-10-19 12:15:55 -070091
Robert Phillips4150eea2018-02-07 17:08:21 -050092 (*graph)[3]->dependsOn((*graph)[4].get());
93 (*graph)[3]->dependsOn((*graph)[5].get());
94 (*graph)[4]->dependsOn((*graph)[6].get());
95 (*graph)[5]->dependsOn((*graph)[6].get());
robertphillips423f6462015-10-19 12:15:55 -070096}
97
98/* Two independent diamonds
99 * 3 7
Robert Phillipsa186c352020-11-17 13:22:05 -0500100 * . . . .
robertphillips423f6462015-10-19 12:15:55 -0700101 * / \ / \
102 * 1 2 5 6
Robert Phillipsa186c352020-11-17 13:22:05 -0500103 * . . . .
robertphillips423f6462015-10-19 12:15:55 -0700104 * \ / \ /
105 * 0 4
106 */
Mike Kleinea3f0142019-03-20 11:12:10 -0500107static void create_graph4(SkTArray<sk_sp<ToolUtils::TopoTestNode>>* graph) {
108 ToolUtils::TopoTestNode::AllocNodes(graph, 8);
robertphillips423f6462015-10-19 12:15:55 -0700109
Robert Phillips4150eea2018-02-07 17:08:21 -0500110 (*graph)[0]->dependsOn((*graph)[1].get());
111 (*graph)[0]->dependsOn((*graph)[2].get());
112 (*graph)[1]->dependsOn((*graph)[3].get());
113 (*graph)[2]->dependsOn((*graph)[3].get());
robertphillips423f6462015-10-19 12:15:55 -0700114
Robert Phillips4150eea2018-02-07 17:08:21 -0500115 (*graph)[4]->dependsOn((*graph)[5].get());
116 (*graph)[4]->dependsOn((*graph)[6].get());
117 (*graph)[5]->dependsOn((*graph)[7].get());
118 (*graph)[6]->dependsOn((*graph)[7].get());
robertphillips423f6462015-10-19 12:15:55 -0700119}
120
Robert Phillipsa186c352020-11-17 13:22:05 -0500121/* Two linked diamonds w/ two loops
122 * 5 6
123 * / . . \
124 * . \ / .
125 * 2 3 4
126 * \ . /
127 * . / \ .
128 * 0 1
129 */
130static void create_graph5(SkTArray<sk_sp<ToolUtils::TopoTestNode>>* graph) {
131 ToolUtils::TopoTestNode::AllocNodes(graph, 7);
132
133 (*graph)[0]->dependsOn((*graph)[3].get());
134 (*graph)[1]->dependsOn((*graph)[3].get());
135 (*graph)[2]->dependsOn((*graph)[0].get());
136 (*graph)[3]->dependsOn((*graph)[5].get());
137 (*graph)[3]->dependsOn((*graph)[6].get());
138 (*graph)[4]->dependsOn((*graph)[1].get());
139 (*graph)[5]->dependsOn((*graph)[2].get());
140 (*graph)[6]->dependsOn((*graph)[4].get());
141}
142
143/* Two disjoint loops
144 * 2 5
145 * / . / .
146 * / \ / \
147 * . \ . \
148 * 0 ---> 1 3 ---> 4
149 */
150static void create_graph6(SkTArray<sk_sp<ToolUtils::TopoTestNode>>* graph) {
151 ToolUtils::TopoTestNode::AllocNodes(graph, 6);
152
153 (*graph)[0]->dependsOn((*graph)[1].get());
154 (*graph)[1]->dependsOn((*graph)[2].get());
155 (*graph)[2]->dependsOn((*graph)[0].get());
156
157 (*graph)[3]->dependsOn((*graph)[4].get());
158 (*graph)[4]->dependsOn((*graph)[5].get());
159 (*graph)[5]->dependsOn((*graph)[3].get());
160}
161
robertphillips423f6462015-10-19 12:15:55 -0700162DEF_TEST(TopoSort, reporter) {
163 SkRandom rand;
164
165 struct {
166 CreateGraphPF fCreate;
167 bool fExpectedResult;
168 } tests[] = {
169 { create_graph0, true },
170 { create_graph1, true },
171 { create_graph2, false },
172 { create_graph3, true },
173 { create_graph4, true },
Robert Phillipsa186c352020-11-17 13:22:05 -0500174 { create_graph5, false },
175 { create_graph6, false },
robertphillips423f6462015-10-19 12:15:55 -0700176 };
177
178 for (size_t i = 0; i < SK_ARRAY_COUNT(tests); ++i) {
Mike Kleinea3f0142019-03-20 11:12:10 -0500179 SkTArray<sk_sp<ToolUtils::TopoTestNode>> graph;
halcanary9d524f22016-03-29 09:03:52 -0700180
robertphillips423f6462015-10-19 12:15:55 -0700181 (tests[i].fCreate)(&graph);
182
Robert Phillipsa186c352020-11-17 13:22:05 -0500183 const int numNodes = graph.count();
184
Mike Kleinea3f0142019-03-20 11:12:10 -0500185 ToolUtils::TopoTestNode::Shuffle(&graph, &rand);
robertphillips423f6462015-10-19 12:15:55 -0700186
Robert Phillipsfbbc3bb2020-11-16 14:58:56 -0500187 bool actualResult = GrTTopoSort<ToolUtils::TopoTestNode>(&graph);
robertphillips423f6462015-10-19 12:15:55 -0700188 REPORTER_ASSERT(reporter, actualResult == tests[i].fExpectedResult);
Robert Phillipsa186c352020-11-17 13:22:05 -0500189 REPORTER_ASSERT(reporter, numNodes == graph.count());
robertphillips423f6462015-10-19 12:15:55 -0700190
191 if (tests[i].fExpectedResult) {
Robert Phillipsa186c352020-11-17 13:22:05 -0500192 for (const auto& node : graph) {
193 REPORTER_ASSERT(reporter, node->check());
194 }
195 } else {
196 // When the topological sort fails all the nodes should still appear in the result
197 // but their order can be somewhat arbitrary.
198 std::vector<bool> seen(numNodes, false);
199
200 for (const auto& node : graph) {
201 SkASSERT(node);
202 SkASSERT(!seen[node->id()]);
203 seen[node->id()] = true;
robertphillips423f6462015-10-19 12:15:55 -0700204 }
205 }
206
207 //SkDEBUGCODE(print(graph);)
robertphillips423f6462015-10-19 12:15:55 -0700208 }
209}