OLD | NEW |
---|---|
(Empty) | |
1 /* | |
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 | |
8 #include "SkRandom.h" | |
9 #include "SkTTopoSort.h" | |
10 #include "Test.h" | |
11 | |
12 /////////////////////////////////////////////////////////////////////////////// | |
13 // Shared with TopoSortBench.cpp | |
bsalomon
2015/10/19 14:19:13
Is there any place we could stick the test node cl
robertphillips
2015/10/19 16:21:07
Done - although we might want to create a top-leve
| |
14 /////////////////////////////////////////////////////////////////////////////// | |
15 | |
16 // A helper object to test the topological sorting code | |
17 class TopoTestNode { | |
18 public: | |
19 TopoTestNode(int id) : fID(id), fOutputPos(-1), fTempMark(false) { } | |
20 | |
21 void dependsOn(TopoTestNode* src) { | |
22 *fDependencies.append() = src; | |
23 } | |
24 | |
25 int id() const { return fID; } | |
26 void reset() { fOutputPos = -1; } | |
27 | |
28 int outputPos() const { return fOutputPos; } | |
29 | |
30 // check that the topological sort is valid for this node | |
31 void check() { | |
32 SkASSERT(-1 != fOutputPos); | |
33 | |
34 for (int i = 0; i < fDependencies.count(); ++i) { | |
35 SkASSERT(-1 != fDependencies[i]->outputPos()); | |
36 // This node should've been output after all the nodes on which it d epends | |
37 SkASSERT(fOutputPos > fDependencies[i]->outputPos()); | |
38 } | |
39 } | |
40 | |
41 // The following 7 methods are needed by the topological sort | |
42 static void SetTempMark(TopoTestNode* node) { node->fTempMark = true; } | |
43 static void ResetTempMark(TopoTestNode* node) { node->fTempMark = false; } | |
44 static bool IsTempMarked(TopoTestNode* node) { return node->fTempMark; } | |
45 static void Output(TopoTestNode* node, int outputPos) { | |
46 SkASSERT(-1 != outputPos); | |
47 node->fOutputPos = outputPos; | |
48 } | |
49 static bool WasOutput(TopoTestNode* node) { return (-1 != node->fOutputPos); } | |
50 static int NumDependencies(TopoTestNode* node) { return node->fDependencies. count(); } | |
51 static TopoTestNode* Dependency(TopoTestNode* node, int index) { | |
52 return node->fDependencies[index]; | |
53 } | |
54 | |
55 private: | |
56 int fID; | |
57 int fOutputPos; | |
58 bool fTempMark; | |
59 | |
60 SkTDArray<TopoTestNode*> fDependencies; | |
61 }; | |
62 | |
63 static void alloc_nodes(SkTDArray<TopoTestNode*>* graph, int num) { | |
64 graph->setReserve(num); | |
65 | |
66 for (int i = 0; i < num; ++i) { | |
67 *graph->append() = new TopoTestNode(i); | |
68 } | |
69 } | |
70 | |
71 static void dealloc_nodes(SkTDArray<TopoTestNode*>* graph) { | |
72 for (int i = 0; i < graph->count(); ++i) { | |
73 delete (*graph)[i]; | |
74 } | |
75 } | |
76 | |
77 #ifdef SK_DEBUG | |
78 static void print(const SkTDArray<TopoTestNode*>& graph) { | |
79 for (int i = 0; i < graph.count(); ++i) { | |
80 SkDebugf("%d, ", graph[i]->id()); | |
81 } | |
82 SkDebugf("\n"); | |
83 } | |
84 #endif | |
85 | |
86 // randomize the array | |
87 static void shuffle(SkTDArray<TopoTestNode*>* graph, SkRandom* rand) { | |
88 for (int i = graph->count()-1; i > 0; --i) { | |
89 int swap = rand->nextU() % (i+1); | |
90 | |
91 TopoTestNode* tmp = (*graph)[i]; | |
92 (*graph)[i] = (*graph)[swap]; | |
93 (*graph)[swap] = tmp; | |
94 } | |
95 } | |
96 | |
97 /////////////////////////////////////////////////////////////////////////////// | |
98 /////////////////////////////////////////////////////////////////////////////// | |
99 | |
100 typedef void (*CreateGraphPF)(SkTDArray<TopoTestNode*>* graph); | |
101 | |
102 // Simple diamond | |
103 // 3 | |
104 // / \ | |
105 // 1 2 | |
106 // \ / | |
107 // 0 | |
108 static void create_graph0(SkTDArray<TopoTestNode*>* graph) { | |
109 alloc_nodes(graph, 4); | |
110 | |
111 (*graph)[0]->dependsOn((*graph)[1]); | |
112 (*graph)[0]->dependsOn((*graph)[2]); | |
113 (*graph)[1]->dependsOn((*graph)[3]); | |
114 (*graph)[2]->dependsOn((*graph)[3]); | |
115 } | |
116 | |
117 // Simple chain | |
118 // 3 | |
119 // | | |
120 // 2 | |
121 // | | |
122 // 1 | |
123 // | | |
124 // 0 | |
125 static void create_graph1(SkTDArray<TopoTestNode*>* graph) { | |
126 alloc_nodes(graph, 4); | |
127 | |
128 (*graph)[0]->dependsOn((*graph)[1]); | |
129 (*graph)[1]->dependsOn((*graph)[2]); | |
130 (*graph)[2]->dependsOn((*graph)[3]); | |
131 } | |
132 | |
133 // Loop | |
134 // 2 | |
135 // / \ | |
136 // 0 --- 1 | |
137 static void create_graph2(SkTDArray<TopoTestNode*>* graph) { | |
138 alloc_nodes(graph, 3); | |
139 | |
140 (*graph)[0]->dependsOn((*graph)[1]); | |
141 (*graph)[1]->dependsOn((*graph)[2]); | |
142 (*graph)[2]->dependsOn((*graph)[0]); | |
143 } | |
144 | |
145 // Double diamond | |
146 // 6 | |
147 // / \ | |
148 // 4 5 | |
149 // \ / | |
150 // 3 | |
151 // / \ | |
152 // 1 2 | |
153 // \ / | |
154 // 0 | |
155 static void create_graph3(SkTDArray<TopoTestNode*>* graph) { | |
156 alloc_nodes(graph, 7); | |
157 | |
158 (*graph)[0]->dependsOn((*graph)[1]); | |
159 (*graph)[0]->dependsOn((*graph)[2]); | |
160 (*graph)[1]->dependsOn((*graph)[3]); | |
161 (*graph)[2]->dependsOn((*graph)[3]); | |
162 | |
163 (*graph)[3]->dependsOn((*graph)[4]); | |
164 (*graph)[3]->dependsOn((*graph)[5]); | |
165 (*graph)[4]->dependsOn((*graph)[6]); | |
166 (*graph)[5]->dependsOn((*graph)[6]); | |
167 } | |
168 | |
169 // Two independent diamonds | |
170 // 3 7 | |
171 // / \ / \ | |
172 // 1 2 5 6 | |
173 // \ / \ / | |
174 // 0 4 | |
175 static void create_graph4(SkTDArray<TopoTestNode*>* graph) { | |
176 alloc_nodes(graph, 8); | |
177 | |
178 (*graph)[0]->dependsOn((*graph)[1]); | |
179 (*graph)[0]->dependsOn((*graph)[2]); | |
180 (*graph)[1]->dependsOn((*graph)[3]); | |
181 (*graph)[2]->dependsOn((*graph)[3]); | |
182 | |
183 (*graph)[4]->dependsOn((*graph)[5]); | |
184 (*graph)[4]->dependsOn((*graph)[6]); | |
185 (*graph)[5]->dependsOn((*graph)[7]); | |
186 (*graph)[6]->dependsOn((*graph)[7]); | |
187 } | |
188 | |
189 DEF_TEST(TopoSort, reporter) { | |
190 SkRandom rand; | |
191 | |
192 struct { | |
193 CreateGraphPF fCreate; | |
194 bool fExpectedResult; | |
195 } tests[] = { | |
196 { create_graph0, true }, | |
197 { create_graph1, true }, | |
198 { create_graph2, false }, | |
199 { create_graph3, true }, | |
200 { create_graph4, true }, | |
201 }; | |
202 | |
203 for (size_t i = 0; i < SK_ARRAY_COUNT(tests); ++i) { | |
204 SkTDArray<TopoTestNode*> graph; | |
205 | |
206 (tests[i].fCreate)(&graph); | |
207 | |
208 shuffle(&graph, &rand); | |
209 | |
210 bool actualResult = SkTTopoSort<TopoTestNode>(&graph); | |
211 REPORTER_ASSERT(reporter, actualResult == tests[i].fExpectedResult); | |
212 | |
213 if (tests[i].fExpectedResult) { | |
214 for (int j = 0; j < graph.count(); ++j) { | |
215 graph[j]->check(); | |
216 } | |
217 } | |
218 | |
219 //SkDEBUGCODE(print(graph);) | |
220 dealloc_nodes(&graph); | |
221 } | |
222 } | |
223 | |
OLD | NEW |