xref: /third_party/mesa3d/src/util/tests/dag_test.cpp (revision bf215546)
1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2021 Google, Inc.
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include <gtest/gtest.h>
25bf215546Sopenharmony_ci#include "util/dag.h"
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ciclass dag_test : public ::testing::Test {
28bf215546Sopenharmony_ciprotected:
29bf215546Sopenharmony_ci   dag_test();
30bf215546Sopenharmony_ci   ~dag_test();
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci   void *mem_ctx;
33bf215546Sopenharmony_ci   struct util_dynarray expect, actual;
34bf215546Sopenharmony_ci   struct dag *dag;
35bf215546Sopenharmony_ci};
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_cidag_test::dag_test()
38bf215546Sopenharmony_ci{
39bf215546Sopenharmony_ci   mem_ctx = ralloc_context(NULL);
40bf215546Sopenharmony_ci   util_dynarray_init(&expect, mem_ctx);
41bf215546Sopenharmony_ci   util_dynarray_init(&actual, mem_ctx);
42bf215546Sopenharmony_ci   dag = dag_create(mem_ctx);
43bf215546Sopenharmony_ci}
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_cidag_test::~dag_test()
46bf215546Sopenharmony_ci{
47bf215546Sopenharmony_ci   ralloc_free(mem_ctx);
48bf215546Sopenharmony_ci}
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_cistruct node: public dag_node {
51bf215546Sopenharmony_ci   int val;
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_ci   /* Overload >> to make describing our test case graphs easier to read */
54bf215546Sopenharmony_ci   struct node &operator>>(struct node &child) {
55bf215546Sopenharmony_ci      dag_add_edge(static_cast<struct dag_node *>(this),
56bf215546Sopenharmony_ci                   static_cast<struct dag_node *>(&child), 0);
57bf215546Sopenharmony_ci      return child;
58bf215546Sopenharmony_ci   }
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci   void add_edge(struct node &child, uintptr_t data) {
61bf215546Sopenharmony_ci      dag_add_edge(static_cast<struct dag_node *>(this),
62bf215546Sopenharmony_ci                   static_cast<struct dag_node *>(&child), data);
63bf215546Sopenharmony_ci   }
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci   void add_edge_max_data(struct node &child, uintptr_t data) {
66bf215546Sopenharmony_ci      dag_add_edge_max_data(static_cast<struct dag_node *>(this),
67bf215546Sopenharmony_ci                            static_cast<struct dag_node *>(&child), data);
68bf215546Sopenharmony_ci   }
69bf215546Sopenharmony_ci};
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_cistatic void output_cb(struct dag_node *dag_node, void *data)
72bf215546Sopenharmony_ci{
73bf215546Sopenharmony_ci   struct node *node = static_cast<struct node *>(dag_node);
74bf215546Sopenharmony_ci   struct util_dynarray *output = (struct util_dynarray *)data;
75bf215546Sopenharmony_ci   util_dynarray_append(output, int, node->val);
76bf215546Sopenharmony_ci}
77bf215546Sopenharmony_ci
78bf215546Sopenharmony_cistatic void
79bf215546Sopenharmony_ciinit_nodes(struct dag *dag, struct node *nodes, unsigned num_nodes)
80bf215546Sopenharmony_ci{
81bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_nodes; i++) {
82bf215546Sopenharmony_ci      dag_init_node(dag, static_cast<struct dag_node *>(&nodes[i]));
83bf215546Sopenharmony_ci      nodes[i].val = i;
84bf215546Sopenharmony_ci   }
85bf215546Sopenharmony_ci}
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci#define INIT_NODES(num_nodes)                            \
88bf215546Sopenharmony_ci   typedef struct { int order[num_nodes]; } result_type; \
89bf215546Sopenharmony_ci   struct node node[(num_nodes)];                        \
90bf215546Sopenharmony_ci   init_nodes(dag, node, (num_nodes))
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci#define SET_EXPECTED(...) do {                           \
93bf215546Sopenharmony_ci	result_type res = {{ __VA_ARGS__ }};             \
94bf215546Sopenharmony_ci	util_dynarray_append(&expect, result_type, res); \
95bf215546Sopenharmony_ci} while (0)
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_cistatic bool
98bf215546Sopenharmony_ciint_dynarrays_equal(struct util_dynarray *a, struct util_dynarray *b)
99bf215546Sopenharmony_ci{
100bf215546Sopenharmony_ci   if (util_dynarray_num_elements(a, int) != util_dynarray_num_elements(b, int))
101bf215546Sopenharmony_ci      return false;
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci   for (unsigned i = 0; i < util_dynarray_num_elements(a, int); i++) {
104bf215546Sopenharmony_ci      if (*util_dynarray_element(a, int, i) !=
105bf215546Sopenharmony_ci          *util_dynarray_element(b, int, i)) {
106bf215546Sopenharmony_ci         return false;
107bf215546Sopenharmony_ci      }
108bf215546Sopenharmony_ci   }
109bf215546Sopenharmony_ci   return true;
110bf215546Sopenharmony_ci}
111bf215546Sopenharmony_ci
112bf215546Sopenharmony_cistatic testing::AssertionResult
113bf215546Sopenharmony_ciint_dynarrays_equal_pred(const char *a_expr,
114bf215546Sopenharmony_ci                         const char *b_expr,
115bf215546Sopenharmony_ci                         struct util_dynarray *a,
116bf215546Sopenharmony_ci                         struct util_dynarray *b)
117bf215546Sopenharmony_ci{
118bf215546Sopenharmony_ci  if (int_dynarrays_equal(a, b)) return testing::AssertionSuccess();
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci   testing::AssertionResult result = testing::AssertionFailure();
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci   result << a_expr << " != " << b_expr;
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci   result << ", (";
125bf215546Sopenharmony_ci   for (unsigned i = 0; i < util_dynarray_num_elements(a, int); i++) {
126bf215546Sopenharmony_ci      if (i != 0)
127bf215546Sopenharmony_ci         result << ", ";
128bf215546Sopenharmony_ci      result << *util_dynarray_element(a, int, i);
129bf215546Sopenharmony_ci   }
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci   result << ") != (";
132bf215546Sopenharmony_ci   for (unsigned i = 0; i < util_dynarray_num_elements(b, int); i++) {
133bf215546Sopenharmony_ci      if (i != 0)
134bf215546Sopenharmony_ci         result << ", ";
135bf215546Sopenharmony_ci      result << *util_dynarray_element(b, int, i);
136bf215546Sopenharmony_ci   }
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   result << ")";
139bf215546Sopenharmony_ci
140bf215546Sopenharmony_ci   return result;
141bf215546Sopenharmony_ci}
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci#define TEST_CHECK() EXPECT_PRED_FORMAT2(int_dynarrays_equal_pred, &expect, &actual)
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ciTEST_F(dag_test, simple)
146bf215546Sopenharmony_ci{
147bf215546Sopenharmony_ci   INIT_NODES(3);
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci   /*     0
150bf215546Sopenharmony_ci    *    / \
151bf215546Sopenharmony_ci    *   1   2
152bf215546Sopenharmony_ci    */
153bf215546Sopenharmony_ci   node[0] >> node[1];
154bf215546Sopenharmony_ci   node[0] >> node[2];
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci   /* Expected traversal order: [1, 2, 0] */
157bf215546Sopenharmony_ci   SET_EXPECTED(1, 2, 0);
158bf215546Sopenharmony_ci
159bf215546Sopenharmony_ci   dag_traverse_bottom_up(dag, output_cb, &actual);
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci   TEST_CHECK();
162bf215546Sopenharmony_ci}
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ciTEST_F(dag_test, duplicate_edge)
165bf215546Sopenharmony_ci{
166bf215546Sopenharmony_ci   INIT_NODES(3);
167bf215546Sopenharmony_ci
168bf215546Sopenharmony_ci   node[0].add_edge(node[1], 0);
169bf215546Sopenharmony_ci   node[0].add_edge(node[1], 1);
170bf215546Sopenharmony_ci   node[0].add_edge(node[2], 0);
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ci   EXPECT_EQ(util_dynarray_num_elements(&node[0].edges, struct dag_edge), 3);
173bf215546Sopenharmony_ci
174bf215546Sopenharmony_ci   SET_EXPECTED(1, 2, 0);
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci   dag_traverse_bottom_up(dag, output_cb, &actual);
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci   TEST_CHECK();
179bf215546Sopenharmony_ci}
180bf215546Sopenharmony_ci
181bf215546Sopenharmony_ciTEST_F(dag_test, duplicate_edge_max_data)
182bf215546Sopenharmony_ci{
183bf215546Sopenharmony_ci   INIT_NODES(3);
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci   node[0].add_edge_max_data(node[1], 0);
186bf215546Sopenharmony_ci   node[0].add_edge_max_data(node[1], 1);
187bf215546Sopenharmony_ci   node[0].add_edge_max_data(node[2], 0);
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci   EXPECT_EQ(util_dynarray_num_elements(&node[0].edges, struct dag_edge), 2);
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci   util_dynarray_foreach (&node[0].edges, struct dag_edge, edge) {
192bf215546Sopenharmony_ci      if (edge->child == &node[1]) {
193bf215546Sopenharmony_ci         EXPECT_EQ(edge->data, 1);
194bf215546Sopenharmony_ci      } else {
195bf215546Sopenharmony_ci         EXPECT_EQ(edge->child, &node[2]);
196bf215546Sopenharmony_ci         EXPECT_EQ(edge->data, 0);
197bf215546Sopenharmony_ci      }
198bf215546Sopenharmony_ci   }
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci   SET_EXPECTED(1, 2, 0);
201bf215546Sopenharmony_ci
202bf215546Sopenharmony_ci   dag_traverse_bottom_up(dag, output_cb, &actual);
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci   TEST_CHECK();
205bf215546Sopenharmony_ci}
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_ciTEST_F(dag_test, simple_many_children)
208bf215546Sopenharmony_ci{
209bf215546Sopenharmony_ci   INIT_NODES(6);
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci   /*     _ 0 _
212bf215546Sopenharmony_ci    *    / /|\ \
213bf215546Sopenharmony_ci    *   / / | \ \
214bf215546Sopenharmony_ci    *  |  | | |  |
215bf215546Sopenharmony_ci    *  1  2 3 4  5
216bf215546Sopenharmony_ci    */
217bf215546Sopenharmony_ci   node[0] >> node[1];
218bf215546Sopenharmony_ci   node[0] >> node[2];
219bf215546Sopenharmony_ci   node[0] >> node[3];
220bf215546Sopenharmony_ci   node[0] >> node[4];
221bf215546Sopenharmony_ci   node[0] >> node[5];
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci   /* Expected traversal order: [1, 2, 3, 4, 5, 0] */
224bf215546Sopenharmony_ci   SET_EXPECTED(1, 2, 3, 4, 5, 0);
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci   dag_traverse_bottom_up(dag, output_cb, &actual);
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci   TEST_CHECK();
229bf215546Sopenharmony_ci}
230bf215546Sopenharmony_ci
231bf215546Sopenharmony_ciTEST_F(dag_test, simple_many_parents)
232bf215546Sopenharmony_ci{
233bf215546Sopenharmony_ci   INIT_NODES(7);
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci   /*     _ 0 _
236bf215546Sopenharmony_ci    *    / /|\ \
237bf215546Sopenharmony_ci    *   / / | \ \
238bf215546Sopenharmony_ci    *  |  | | |  |
239bf215546Sopenharmony_ci    *  1  2 3 4  5
240bf215546Sopenharmony_ci    *  |  | | |  |
241bf215546Sopenharmony_ci    *   \ \ | / /
242bf215546Sopenharmony_ci    *    \ \|/ /
243bf215546Sopenharmony_ci    *     ‾ 6 ‾
244bf215546Sopenharmony_ci    */
245bf215546Sopenharmony_ci   node[0] >> node[1] >> node[6];
246bf215546Sopenharmony_ci   node[0] >> node[2] >> node[6];
247bf215546Sopenharmony_ci   node[0] >> node[3] >> node[6];
248bf215546Sopenharmony_ci   node[0] >> node[4] >> node[6];
249bf215546Sopenharmony_ci   node[0] >> node[5] >> node[6];
250bf215546Sopenharmony_ci
251bf215546Sopenharmony_ci   /* Expected traversal order: [6, 1, 2, 3, 4, 5, 0] */
252bf215546Sopenharmony_ci   SET_EXPECTED(6, 1, 2, 3, 4, 5, 0);
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci   dag_traverse_bottom_up(dag, output_cb, &actual);
255bf215546Sopenharmony_ci
256bf215546Sopenharmony_ci   TEST_CHECK();
257bf215546Sopenharmony_ci}
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ciTEST_F(dag_test, complex)
260bf215546Sopenharmony_ci{
261bf215546Sopenharmony_ci   INIT_NODES(6);
262bf215546Sopenharmony_ci
263bf215546Sopenharmony_ci   /*     0
264bf215546Sopenharmony_ci    *    / \
265bf215546Sopenharmony_ci    *   1   3
266bf215546Sopenharmony_ci    *  / \  |\
267bf215546Sopenharmony_ci    * 2  |  | \
268bf215546Sopenharmony_ci    *  \ / /   5
269bf215546Sopenharmony_ci    *   4 ‾
270bf215546Sopenharmony_ci    */
271bf215546Sopenharmony_ci   node[0] >> node[1] >> node[2] >> node[4];
272bf215546Sopenharmony_ci   node[1] >> node[4];
273bf215546Sopenharmony_ci   node[0] >> node[3];
274bf215546Sopenharmony_ci   node[3] >> node[4];
275bf215546Sopenharmony_ci   node[3] >> node[5];
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci   /* Expected traversal order: [4, 2, 1, 5, 3, 0] */
278bf215546Sopenharmony_ci   SET_EXPECTED(4, 2, 1, 5, 3, 0);
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci   dag_traverse_bottom_up(dag, output_cb, &actual);
281bf215546Sopenharmony_ci
282bf215546Sopenharmony_ci   TEST_CHECK();
283bf215546Sopenharmony_ci}
284