blob: 431cbee5f8318da104320fe78057a0745c73972d [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2015 The Bazel Authors. All rights reserved.
Ulf Adams89f012d2015-02-26 13:39:28 +00002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.syntax;
15
Ulf Adams795895a2015-03-06 15:58:35 +000016import static com.google.common.truth.Truth.assertThat;
michajlo660d17f2020-03-27 09:01:57 -070017import static org.junit.Assert.assertThrows;
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000018
cparsonsa7c0afb2019-08-30 08:14:51 -070019import com.google.devtools.build.lib.collect.nestedset.NestedSet;
Ulf Adams89f012d2015-02-26 13:39:28 +000020import com.google.devtools.build.lib.collect.nestedset.Order;
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +000021import com.google.devtools.build.lib.syntax.util.EvaluationTestCase;
Pedro Liberal Fernandez45bddab2017-01-11 13:31:14 +000022import java.util.Arrays;
23import java.util.HashMap;
24import java.util.List;
25import java.util.Map;
Dmitry Lomovcdb6ef52016-08-05 08:38:26 +000026import org.junit.Test;
27import org.junit.runner.RunWith;
28import org.junit.runners.JUnit4;
Florian Weikertb914f3c2015-07-29 13:35:19 +000029
Googlerd21a0d12019-11-21 13:52:30 -080030/** Tests for Depset. */
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000031@RunWith(JUnit4.class)
adonovan6ea8e252020-02-03 14:33:14 -080032public final class DepsetTest extends EvaluationTestCase {
Ulf Adams89f012d2015-02-26 13:39:28 +000033
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000034 @Test
Jon Brandveinc8e1cfb2017-01-19 18:43:37 +000035 public void testConstructor() throws Exception {
Googler1a1fca22019-10-14 09:31:22 -070036 exec("s = depset(order='default')");
Googlerd21a0d12019-11-21 13:52:30 -080037 assertThat(lookup("s")).isInstanceOf(Depset.class);
Ulf Adams89f012d2015-02-26 13:39:28 +000038 }
39
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000040 @Test
Googlerbbde2292019-11-21 12:51:51 -080041 public void testTuples() throws Exception {
Googler1a1fca22019-10-14 09:31:22 -070042 exec(
cparsonsa5b764f2018-12-06 15:07:58 -080043 "s_one = depset([('1', '2'), ('3', '4')])",
44 "s_two = depset(direct = [('1', '2'), ('3', '4'), ('5', '6')])",
45 "s_three = depset(transitive = [s_one, s_two])",
46 "s_four = depset(direct = [('1', '3')], transitive = [s_one, s_two])",
cparsonse210bec2019-01-03 14:33:38 -080047 "s_five = depset(direct = [('1', '3', '5')], transitive = [s_one, s_two])",
cparsonsa5b764f2018-12-06 15:07:58 -080048 "s_six = depset(transitive = [s_one, s_five])",
49 "s_seven = depset(direct = [('1', '3')], transitive = [s_one, s_five])",
Googlerbbde2292019-11-21 12:51:51 -080050 "s_eight = depset(direct = [(1, 3)], transitive = [s_one, s_two])"); // note, tuple of int
51 assertThat(get("s_one").getContentType()).isEqualTo(SkylarkType.TUPLE);
52 assertThat(get("s_two").getContentType()).isEqualTo(SkylarkType.TUPLE);
53 assertThat(get("s_three").getContentType()).isEqualTo(SkylarkType.TUPLE);
cparsonsa5b764f2018-12-06 15:07:58 -080054 assertThat(get("s_eight").getContentType()).isEqualTo(SkylarkType.TUPLE);
cparsonse210bec2019-01-03 14:33:38 -080055
ulfjack512244b2020-01-14 05:15:08 -080056 assertThat(get("s_four").getSet(Tuple.class).toList())
cparsonse210bec2019-01-03 14:33:38 -080057 .containsExactly(
58 Tuple.of("1", "3"), Tuple.of("1", "2"), Tuple.of("3", "4"), Tuple.of("5", "6"));
ulfjack512244b2020-01-14 05:15:08 -080059 assertThat(get("s_five").getSet(Tuple.class).toList())
cparsonse210bec2019-01-03 14:33:38 -080060 .containsExactly(
61 Tuple.of("1", "3", "5"), Tuple.of("1", "2"), Tuple.of("3", "4"), Tuple.of("5", "6"));
ulfjack512244b2020-01-14 05:15:08 -080062 assertThat(get("s_eight").getSet(Tuple.class).toList())
cparsonse210bec2019-01-03 14:33:38 -080063 .containsExactly(
64 Tuple.of(1, 3), Tuple.of("1", "2"), Tuple.of("3", "4"), Tuple.of("5", "6"));
cparsonsa5b764f2018-12-06 15:07:58 -080065 }
66
67 @Test
Jon Brandveinb3d0bdd2017-01-13 17:46:29 +000068 public void testGetSet() throws Exception {
Googler1a1fca22019-10-14 09:31:22 -070069 exec("s = depset(['a', 'b'])");
ulfjack512244b2020-01-14 05:15:08 -080070 assertThat(get("s").getSet(String.class).toList()).containsExactly("a", "b").inOrder();
71 assertThat(get("s").getSet(Object.class).toList()).containsExactly("a", "b").inOrder();
Googlerd21a0d12019-11-21 13:52:30 -080072 assertThrows(Depset.TypeException.class, () -> get("s").getSet(Integer.class));
Jon Brandveinb3d0bdd2017-01-13 17:46:29 +000073 }
74
75 @Test
dslomov2317ef82017-09-28 11:19:54 -040076 public void testGetSetDirect() throws Exception {
Googler1a1fca22019-10-14 09:31:22 -070077 exec("s = depset(direct = ['a', 'b'])");
ulfjack512244b2020-01-14 05:15:08 -080078 assertThat(get("s").getSet(String.class).toList()).containsExactly("a", "b").inOrder();
79 assertThat(get("s").getSet(Object.class).toList()).containsExactly("a", "b").inOrder();
Googlerd21a0d12019-11-21 13:52:30 -080080 assertThrows(Depset.TypeException.class, () -> get("s").getSet(Integer.class));
dslomov2317ef82017-09-28 11:19:54 -040081 }
82
83 @Test
84 public void testGetSetItems() throws Exception {
Googler1a1fca22019-10-14 09:31:22 -070085 exec("s = depset(items = ['a', 'b'])");
ulfjack512244b2020-01-14 05:15:08 -080086 assertThat(get("s").getSet(String.class).toList()).containsExactly("a", "b").inOrder();
87 assertThat(get("s").getSet(Object.class).toList()).containsExactly("a", "b").inOrder();
Googlerd21a0d12019-11-21 13:52:30 -080088 assertThrows(Depset.TypeException.class, () -> get("s").getSet(Integer.class));
dslomov2317ef82017-09-28 11:19:54 -040089 }
90
91
92 @Test
Jon Brandvein3cfeeec2017-01-20 04:23:37 +000093 public void testToCollection() throws Exception {
Googler1a1fca22019-10-14 09:31:22 -070094 exec("s = depset(['a', 'b'])");
Jon Brandvein3cfeeec2017-01-20 04:23:37 +000095 assertThat(get("s").toCollection(String.class)).containsExactly("a", "b").inOrder();
96 assertThat(get("s").toCollection(Object.class)).containsExactly("a", "b").inOrder();
97 assertThat(get("s").toCollection()).containsExactly("a", "b").inOrder();
Googlerd21a0d12019-11-21 13:52:30 -080098 assertThrows(Depset.TypeException.class, () -> get("s").toCollection(Integer.class));
dslomov2317ef82017-09-28 11:19:54 -040099 }
100
101 @Test
102 public void testToCollectionDirect() throws Exception {
Googler1a1fca22019-10-14 09:31:22 -0700103 exec("s = depset(direct = ['a', 'b'])");
dslomov2317ef82017-09-28 11:19:54 -0400104 assertThat(get("s").toCollection(String.class)).containsExactly("a", "b").inOrder();
105 assertThat(get("s").toCollection(Object.class)).containsExactly("a", "b").inOrder();
106 assertThat(get("s").toCollection()).containsExactly("a", "b").inOrder();
Googlerd21a0d12019-11-21 13:52:30 -0800107 assertThrows(Depset.TypeException.class, () -> get("s").toCollection(Integer.class));
dslomov2317ef82017-09-28 11:19:54 -0400108 }
109
110 @Test
111 public void testToCollectionItems() throws Exception {
Googler1a1fca22019-10-14 09:31:22 -0700112 exec("s = depset(items = ['a', 'b'])");
dslomov2317ef82017-09-28 11:19:54 -0400113 assertThat(get("s").toCollection(String.class)).containsExactly("a", "b").inOrder();
114 assertThat(get("s").toCollection(Object.class)).containsExactly("a", "b").inOrder();
115 assertThat(get("s").toCollection()).containsExactly("a", "b").inOrder();
Googlerd21a0d12019-11-21 13:52:30 -0800116 assertThrows(Depset.TypeException.class, () -> get("s").toCollection(Integer.class));
Jon Brandvein3cfeeec2017-01-20 04:23:37 +0000117 }
118
119 @Test
Jon Brandveinc8e1cfb2017-01-19 18:43:37 +0000120 public void testOrder() throws Exception {
Googler1a1fca22019-10-14 09:31:22 -0700121 exec("s = depset(['a', 'b'], order='postorder')");
Jon Brandvein052f9ce2017-01-19 21:50:34 +0000122 assertThat(get("s").getSet(String.class).getOrder()).isEqualTo(Order.COMPILE_ORDER);
123 }
124
125 @Test
dslomov2317ef82017-09-28 11:19:54 -0400126 public void testOrderDirect() throws Exception {
Googler1a1fca22019-10-14 09:31:22 -0700127 exec("s = depset(direct = ['a', 'b'], order='postorder')");
dslomov2317ef82017-09-28 11:19:54 -0400128 assertThat(get("s").getSet(String.class).getOrder()).isEqualTo(Order.COMPILE_ORDER);
129 }
130
131 @Test
132 public void testOrderItems() throws Exception {
Googler1a1fca22019-10-14 09:31:22 -0700133 exec("s = depset(items = ['a', 'b'], order='postorder')");
dslomov2317ef82017-09-28 11:19:54 -0400134 assertThat(get("s").getSet(String.class).getOrder()).isEqualTo(Order.COMPILE_ORDER);
135 }
136
137 @Test
Jon Brandveinc8e1cfb2017-01-19 18:43:37 +0000138 public void testBadOrder() throws Exception {
adonovan469d8552020-02-11 09:07:25 -0800139 new Scenario()
140 .testIfExactError("Invalid order: non_existing", "depset(['a'], order='non_existing')");
Jon Brandvein5b792dc2017-01-12 20:22:07 +0000141 }
142
143 @Test
dslomov2317ef82017-09-28 11:19:54 -0400144 public void testBadOrderDirect() throws Exception {
adonovan469d8552020-02-11 09:07:25 -0800145 new Scenario()
146 .testIfExactError(
147 "Invalid order: non_existing", "depset(direct = ['a'], order='non_existing')");
dslomov2317ef82017-09-28 11:19:54 -0400148 }
149
150 @Test
151 public void testBadOrderItems() throws Exception {
adonovan469d8552020-02-11 09:07:25 -0800152 new Scenario()
153 .testIfExactError(
154 "Invalid order: non_existing", "depset(items = ['a'], order='non_existing')");
dslomov2317ef82017-09-28 11:19:54 -0400155 }
156
157 @Test
Jon Brandveinc8e1cfb2017-01-19 18:43:37 +0000158 public void testEmptyGenericType() throws Exception {
Googler1a1fca22019-10-14 09:31:22 -0700159 exec("s = depset()");
Jon Brandveinc8e1cfb2017-01-19 18:43:37 +0000160 assertThat(get("s").getContentType()).isEqualTo(SkylarkType.TOP);
Jon Brandveinb3d0bdd2017-01-13 17:46:29 +0000161 }
162
163 @Test
Jon Brandveinc8e1cfb2017-01-19 18:43:37 +0000164 public void testHomogeneousGenericType() throws Exception {
Googler1a1fca22019-10-14 09:31:22 -0700165 exec("s = depset(['a', 'b', 'c'])");
Jon Brandveinc8e1cfb2017-01-19 18:43:37 +0000166 assertThat(get("s").getContentType()).isEqualTo(SkylarkType.of(String.class));
Jon Brandvein5b792dc2017-01-12 20:22:07 +0000167 }
168
169 @Test
dslomov2317ef82017-09-28 11:19:54 -0400170 public void testHomogeneousGenericTypeDirect() throws Exception {
Googler1a1fca22019-10-14 09:31:22 -0700171 exec("s = depset(['a', 'b', 'c'], transitive = [])");
dslomov2317ef82017-09-28 11:19:54 -0400172 assertThat(get("s").getContentType()).isEqualTo(SkylarkType.of(String.class));
173 }
174
175 @Test
176 public void testHomogeneousGenericTypeItems() throws Exception {
Googler1a1fca22019-10-14 09:31:22 -0700177 exec("s = depset(items = ['a', 'b', 'c'], transitive = [])");
dslomov2317ef82017-09-28 11:19:54 -0400178 assertThat(get("s").getContentType()).isEqualTo(SkylarkType.of(String.class));
179 }
180
181 @Test
182 public void testHomogeneousGenericTypeTransitive() throws Exception {
Googler1a1fca22019-10-14 09:31:22 -0700183 exec("s = depset(['a', 'b', 'c'], transitive = [depset(['x'])])");
dslomov2317ef82017-09-28 11:19:54 -0400184 assertThat(get("s").getContentType()).isEqualTo(SkylarkType.of(String.class));
185 }
186
187 @Test
188 public void testTransitiveIncompatibleOrder() throws Exception {
189 checkEvalError(
190 "Order 'postorder' is incompatible with order 'topological'",
191 "depset(['a', 'b'], order='postorder',",
192 " transitive = [depset(['c', 'd'], order='topological')])");
193 }
194
195 @Test
Jon Brandveinc8e1cfb2017-01-19 18:43:37 +0000196 public void testBadGenericType() throws Exception {
adonovan469d8552020-02-11 09:07:25 -0800197 new Scenario()
198 .testIfExactError(
199 "cannot add an item of type 'int' to a depset of 'string'", "depset(['a', 5])");
Jon Brandveinc8e1cfb2017-01-19 18:43:37 +0000200 }
201
202 @Test
dslomov2317ef82017-09-28 11:19:54 -0400203 public void testBadGenericTypeDirect() throws Exception {
adonovan469d8552020-02-11 09:07:25 -0800204 new Scenario()
205 .testIfExactError(
206 "cannot add an item of type 'int' to a depset of 'string'",
207 "depset(direct = ['a', 5])");
dslomov2317ef82017-09-28 11:19:54 -0400208 }
209
210 @Test
211 public void testBadGenericTypeItems() throws Exception {
adonovan469d8552020-02-11 09:07:25 -0800212 new Scenario()
213 .testIfExactError(
214 "cannot add an item of type 'int' to a depset of 'string'", "depset(items = ['a', 5])");
dslomov2317ef82017-09-28 11:19:54 -0400215 }
216
217 @Test
218 public void testBadGenericTypeTransitive() throws Exception {
adonovan469d8552020-02-11 09:07:25 -0800219 new Scenario()
220 .testIfExactError(
221 "cannot add an item of type 'int' to a depset of 'string'",
222 "depset(['a', 'b'], transitive=[depset([1])])");
dslomov2317ef82017-09-28 11:19:54 -0400223 }
224
225 @Test
226 public void testLegacyAndNewApi() throws Exception {
adonovan469d8552020-02-11 09:07:25 -0800227 new Scenario()
228 .testIfExactError(
229 "Do not pass both 'direct' and 'items' argument to depset constructor.",
230 "depset(['a', 'b'], direct = ['c', 'd'])");
dslomov2317ef82017-09-28 11:19:54 -0400231 }
232
233 @Test
234 public void testItemsAndTransitive() throws Exception {
adonovan469d8552020-02-11 09:07:25 -0800235 new Scenario()
236 .testIfExactError(
adonovan85803902020-04-16 14:46:57 -0700237 "for items, got depset, want sequence",
adonovan469d8552020-02-11 09:07:25 -0800238 "depset(items = depset(), transitive = [depset()])");
dslomov2317ef82017-09-28 11:19:54 -0400239 }
240
241 @Test
242 public void testTooManyPositionals() throws Exception {
adonovan469d8552020-02-11 09:07:25 -0800243 new Scenario()
cparsons7ac265d2019-04-16 15:31:17 -0700244 .testIfErrorContains(
adonovan3f602f22020-01-08 10:28:10 -0800245 "depset() accepts no more than 2 positional arguments but got 3",
246 "depset([], 'default', [])");
dslomov2317ef82017-09-28 11:19:54 -0400247 }
248
249
250 @Test
251 public void testTransitiveOrder() throws Exception {
252 assertContainsInOrder("depset([], transitive=[depset(['a', 'b', 'c'])])", "a", "b", "c");
253 assertContainsInOrder("depset(['a'], transitive = [depset(['b', 'c'])])", "b", "c", "a");
254 assertContainsInOrder("depset(['a', 'b'], transitive = [depset(['c'])])", "c", "a", "b");
255 assertContainsInOrder("depset(['a', 'b', 'c'], transitive = [depset([])])", "a", "b", "c");
256 }
257
258 @Test
259 public void testTransitiveOrderItems() throws Exception {
260 assertContainsInOrder("depset(items=[], transitive=[depset(['a', 'b', 'c'])])", "a", "b", "c");
261 assertContainsInOrder("depset(items=['a'], transitive = [depset(['b', 'c'])])", "b", "c", "a");
262 assertContainsInOrder("depset(items=['a', 'b'], transitive = [depset(['c'])])", "c", "a", "b");
263 assertContainsInOrder("depset(items=['a', 'b', 'c'], transitive = [depset([])])",
264 "a", "b", "c");
265 }
266
267 @Test
268 public void testTransitiveOrderDirect() throws Exception {
269 assertContainsInOrder("depset(direct=[], transitive=[depset(['a', 'b', 'c'])])", "a", "b", "c");
270 assertContainsInOrder("depset(direct=['a'], transitive = [depset(['b', 'c'])])", "b", "c", "a");
271 assertContainsInOrder("depset(direct=['a', 'b'], transitive = [depset(['c'])])", "c", "a", "b");
272 assertContainsInOrder("depset(direct=['a', 'b', 'c'], transitive = [depset([])])",
273 "a", "b", "c");
274 }
275
276 @Test
laurentlb2bbda4a2017-12-07 10:38:46 -0800277 public void testIncompatibleUnion() throws Exception {
laurentlb80735082020-03-27 07:35:09 -0700278 new Scenario()
279 .testIfErrorContains("unsupported binary operation: depset + list", "depset([]) + ['a']");
laurentlb2bbda4a2017-12-07 10:38:46 -0800280
laurentlb80735082020-03-27 07:35:09 -0700281 new Scenario()
282 .testIfErrorContains("unsupported binary operation: depset | list", "depset([]) | ['a']");
laurentlb2bbda4a2017-12-07 10:38:46 -0800283 }
284
Jon Brandvein5b792dc2017-01-12 20:22:07 +0000285 private void assertContainsInOrder(String statement, Object... expectedElements)
286 throws Exception {
Googlerd21a0d12019-11-21 13:52:30 -0800287 assertThat(((Depset) eval(statement)).toCollection())
dslomov2317ef82017-09-28 11:19:54 -0400288 .containsExactly(expectedElements)
289 .inOrder();
Ulf Adams89f012d2015-02-26 13:39:28 +0000290 }
291
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000292 @Test
Jon Brandveinc8e1cfb2017-01-19 18:43:37 +0000293 public void testToString() throws Exception {
laurentlb80735082020-03-27 07:35:09 -0700294 exec("s = depset([3, 4, 5], transitive = [depset([2, 4, 6])])", "x = str(s)");
Vladimir Moskvaba4f0bb2017-01-30 15:45:49 +0000295 assertThat(lookup("x")).isEqualTo("depset([2, 4, 6, 3, 5])");
Ulf Adams89f012d2015-02-26 13:39:28 +0000296 }
297
Laurent Le Brunc7a6e362015-03-09 20:55:40 +0000298 @Test
Jon Brandveinc8e1cfb2017-01-19 18:43:37 +0000299 public void testToStringWithOrder() throws Exception {
Googler1a1fca22019-10-14 09:31:22 -0700300 exec(
laurentlb80735082020-03-27 07:35:09 -0700301 "s = depset([3, 4, 5], transitive = [depset([2, 4, 6])], ",
302 " order = 'topological')",
Jon Brandvein5b792dc2017-01-12 20:22:07 +0000303 "x = str(s)");
laurentlb80735082020-03-27 07:35:09 -0700304 assertThat(lookup("x")).isEqualTo("depset([3, 5, 6, 4, 2], order = \"topological\")");
Laurent Le Brunc7a6e362015-03-09 20:55:40 +0000305 }
306
Googlerd21a0d12019-11-21 13:52:30 -0800307 private Depset get(String varname) throws Exception {
308 return (Depset) lookup(varname);
Ulf Adams89f012d2015-02-26 13:39:28 +0000309 }
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000310
Florian Weikertb914f3c2015-07-29 13:35:19 +0000311 @Test
Jon Brandveinb3d0bdd2017-01-13 17:46:29 +0000312 public void testToList() throws Exception {
laurentlb80735082020-03-27 07:35:09 -0700313 setSemantics();
314 exec("s = depset([3, 4, 5], transitive = [depset([2, 4, 6])])", "x = s.to_list()");
Jon Brandveinb3d0bdd2017-01-13 17:46:29 +0000315 Object value = lookup("x");
Googler942e1c42019-11-12 13:11:44 -0800316 assertThat(value).isInstanceOf(StarlarkList.class);
Jon Brandveinb3d0bdd2017-01-13 17:46:29 +0000317 assertThat((Iterable<?>) value).containsExactly(2, 4, 6, 3, 5).inOrder();
318 }
319
320 @Test
Jon Brandveinc8e1cfb2017-01-19 18:43:37 +0000321 public void testOrderCompatibility() throws Exception {
Florian Weikertb914f3c2015-07-29 13:35:19 +0000322 // Two sets are compatible if
323 // (a) both have the same order or
Jon Brandvein052f9ce2017-01-19 21:50:34 +0000324 // (b) at least one order is "default"
Florian Weikertb914f3c2015-07-29 13:35:19 +0000325
326 for (Order first : Order.values()) {
Googlerae586a02019-11-22 11:10:37 -0800327 Depset s1 = Depset.legacyOf(first, Tuple.of("1", "11"));
Florian Weikertb914f3c2015-07-29 13:35:19 +0000328
329 for (Order second : Order.values()) {
Googlerae586a02019-11-22 11:10:37 -0800330 Depset s2 = Depset.legacyOf(second, Tuple.of("2", "22"));
Florian Weikertb914f3c2015-07-29 13:35:19 +0000331
332 boolean compatible = true;
333
334 try {
Googlerae586a02019-11-22 11:10:37 -0800335 Depset.unionOf(s1, s2);
Florian Weikertb914f3c2015-07-29 13:35:19 +0000336 } catch (Exception ex) {
337 compatible = false;
338 }
339
340 assertThat(compatible).isEqualTo(areOrdersCompatible(first, second));
341 }
342 }
343 }
344
345 private boolean areOrdersCompatible(Order first, Order second) {
346 return first == Order.STABLE_ORDER || second == Order.STABLE_ORDER || first == second;
347 }
Pedro Liberal Fernandez45bddab2017-01-11 13:31:14 +0000348
349 @Test
Jon Brandveinc8e1cfb2017-01-19 18:43:37 +0000350 public void testOrderComplexUnion() throws Exception {
Pedro Liberal Fernandez45bddab2017-01-11 13:31:14 +0000351 // {1, 11, {2, 22}, {3, 33}, {4, 44}}
352 List<String> preOrder = Arrays.asList("1", "11", "2", "22", "3", "33", "4", "44");
353 List<String> postOrder = Arrays.asList("2", "22", "3", "33", "4", "44", "1", "11");
354
janakr889f5622018-03-16 17:49:11 -0700355 MergeStrategy strategy =
356 new MergeStrategy() {
357 @Override
Googlerd21a0d12019-11-21 13:52:30 -0800358 public Depset merge(Depset[] sets) throws Exception {
Googlerae586a02019-11-22 11:10:37 -0800359 Depset union = Depset.unionOf(sets[0], sets[1]);
360 union = Depset.unionOf(union, sets[2]);
361 union = Depset.unionOf(union, sets[3]);
Pedro Liberal Fernandez45bddab2017-01-11 13:31:14 +0000362
janakr889f5622018-03-16 17:49:11 -0700363 return union;
364 }
365 };
Pedro Liberal Fernandez45bddab2017-01-11 13:31:14 +0000366
367 runComplexOrderTest(strategy, preOrder, postOrder);
368 }
369
370 @Test
Jon Brandveinc8e1cfb2017-01-19 18:43:37 +0000371 public void testOrderBalancedTree() throws Exception {
Pedro Liberal Fernandez45bddab2017-01-11 13:31:14 +0000372 // {{1, 11, {2, 22}}, {3, 33, {4, 44}}}
373 List<String> preOrder = Arrays.asList("1", "11", "2", "22", "3", "33", "4", "44");
374 List<String> postOrder = Arrays.asList("2", "22", "4", "44", "3", "33", "1", "11");
375
janakr889f5622018-03-16 17:49:11 -0700376 MergeStrategy strategy =
377 new MergeStrategy() {
378 @Override
Googlerd21a0d12019-11-21 13:52:30 -0800379 public Depset merge(Depset[] sets) throws Exception {
Googlerae586a02019-11-22 11:10:37 -0800380 Depset leftUnion = Depset.unionOf(sets[0], sets[1]);
381 Depset rightUnion = Depset.unionOf(sets[2], sets[3]);
382 Depset union = Depset.unionOf(leftUnion, rightUnion);
Pedro Liberal Fernandez45bddab2017-01-11 13:31:14 +0000383
janakr889f5622018-03-16 17:49:11 -0700384 return union;
385 }
386 };
Pedro Liberal Fernandez45bddab2017-01-11 13:31:14 +0000387
388 runComplexOrderTest(strategy, preOrder, postOrder);
389 }
390
391 @Test
Jon Brandveinc8e1cfb2017-01-19 18:43:37 +0000392 public void testOrderManyLevelsOfNesting() throws Exception {
Pedro Liberal Fernandez45bddab2017-01-11 13:31:14 +0000393 // {1, 11, {2, 22, {3, 33, {4, 44}}}}
394 List<String> preOrder = Arrays.asList("1", "11", "2", "22", "3", "33", "4", "44");
395 List<String> postOrder = Arrays.asList("4", "44", "3", "33", "2", "22", "1", "11");
396
janakr889f5622018-03-16 17:49:11 -0700397 MergeStrategy strategy =
398 new MergeStrategy() {
399 @Override
Googlerd21a0d12019-11-21 13:52:30 -0800400 public Depset merge(Depset[] sets) throws Exception {
Googlerae586a02019-11-22 11:10:37 -0800401 Depset union = Depset.unionOf(sets[2], sets[3]);
402 union = Depset.unionOf(sets[1], union);
403 union = Depset.unionOf(sets[0], union);
Pedro Liberal Fernandez45bddab2017-01-11 13:31:14 +0000404
janakr889f5622018-03-16 17:49:11 -0700405 return union;
406 }
407 };
Pedro Liberal Fernandez45bddab2017-01-11 13:31:14 +0000408
409 runComplexOrderTest(strategy, preOrder, postOrder);
410 }
411
cparsonsa7c0afb2019-08-30 08:14:51 -0700412 @Test
Googler7450e102019-11-26 13:52:51 -0800413 public void testMutableDepsetElementsLegacyBehavior() throws Exception {
414 // See b/144992997 and github.com/bazelbuild/bazel/issues/10313.
adonovan469d8552020-02-11 09:07:25 -0800415 setSemantics("--incompatible_always_check_depset_elements=false");
Googlerbf1eaed2019-11-25 09:52:57 -0800416
Googler7450e102019-11-26 13:52:51 -0800417 // Test legacy depset(...) and new depset(direct=...) constructors.
418
419 // mutable list should be an error
420 checkEvalError("depset elements must not be mutable values", "depset([[1,2,3]])");
421 checkEvalError("depsets cannot contain items of type 'list'", "depset(direct=[[1,2,3]])");
422
423 // struct containing mutable list should be an error
424 checkEvalError("depset elements must not be mutable values", "depset([struct(a=[])])");
425 eval("depset(direct=[struct(a=[])])"); // no error (!)
426
427 // tuple of frozen list currently gives no error (this may change)
428 update("x", StarlarkList.empty());
429 eval("depset([(x,)])");
430 eval("depset(direct=[(x,)])");
431
432 // any list (even frozen) is an error, even with legacy constructor
433 checkEvalError("depsets cannot contain items of type 'list'", "depset([x])");
434 checkEvalError("depsets cannot contain items of type 'list'", "depset(direct=[x])");
435
436 // toplevel dict is an error, even with legacy constructor
437 checkEvalError("depset elements must not be mutable values", "depset([{}])");
438 checkEvalError("depsets cannot contain items of type 'dict'", "depset(direct=[{}])");
439
440 // struct containing dict should be an error
441 checkEvalError("depset elements must not be mutable values", "depset([struct(a={})])");
442 eval("depset(direct=[struct(a={})])"); // no error (!)
443 }
444
445 @Test
446 public void testMutableDepsetElementsDesiredBehavior() throws Exception {
447 // See b/144992997 and github.com/bazelbuild/bazel/issues/10313.
adonovan469d8552020-02-11 09:07:25 -0800448 setSemantics("--incompatible_always_check_depset_elements=true");
Googler7450e102019-11-26 13:52:51 -0800449
450 // Test legacy depset(...) and new depset(direct=...) constructors.
451
452 // mutable list should be an error
Googlerbf1eaed2019-11-25 09:52:57 -0800453 checkEvalError("depset elements must not be mutable values", "depset([[1,2,3]])");
454 checkEvalError("depset elements must not be mutable values", "depset(direct=[[1,2,3]])");
455
Googler7450e102019-11-26 13:52:51 -0800456 // struct containing mutable list should be an error
Googlerbf1eaed2019-11-25 09:52:57 -0800457 checkEvalError("depset elements must not be mutable values", "depset([struct(a=[])])");
458 checkEvalError("depset elements must not be mutable values", "depset(direct=[struct(a=[])])");
459
Googler7450e102019-11-26 13:52:51 -0800460 // tuple of frozen list currently gives no error (this may change)
Googlerbf1eaed2019-11-25 09:52:57 -0800461 update("x", StarlarkList.empty());
Googler7450e102019-11-26 13:52:51 -0800462 eval("depset([(x,)])");
463 eval("depset(direct=[(x,)])");
464
465 // any list (even frozen) is an error, even with legacy constructor
466 checkEvalError("depsets cannot contain items of type 'list'", "depset([x,])");
467 checkEvalError("depsets cannot contain items of type 'list'", "depset(direct=[x,])");
468
469 // toplevel dict is an error, even with legacy constructor
470 checkEvalError("depset elements must not be mutable values", "depset([{}])");
471 checkEvalError("depset elements must not be mutable values", "depset(direct=[{}])");
472
473 // struct containing dict should be an error
474 checkEvalError("depset elements must not be mutable values", "depset([struct(a={})])");
475 checkEvalError("depset elements must not be mutable values", "depset(direct=[struct(a={})])");
Googlerbf1eaed2019-11-25 09:52:57 -0800476 }
477
478 @Test
cparsonsa7c0afb2019-08-30 08:14:51 -0700479 public void testDepthExceedsLimitDuringIteration() throws Exception {
480 NestedSet.setApplicationDepthLimit(2000);
adonovan469d8552020-02-11 09:07:25 -0800481 new Scenario()
cparsonsa7c0afb2019-08-30 08:14:51 -0700482 .setUp(
483 "def create_depset(depth):",
484 " x = depset([0])",
485 " for i in range(1, depth):",
486 " x = depset([i], transitive = [x])",
laurentlb9f9f5ec2019-11-15 10:37:49 -0800487 " for element in x.to_list():",
cparsonsa7c0afb2019-08-30 08:14:51 -0700488 " str(x)",
489 " return None")
490 .testEval("create_depset(1000)", "None")
491 .testIfErrorContains("depset exceeded maximum depth 2000", "create_depset(3000)");
492 }
493
Pedro Liberal Fernandez45bddab2017-01-11 13:31:14 +0000494 private interface MergeStrategy {
Googlerd21a0d12019-11-21 13:52:30 -0800495 Depset merge(Depset[] sets) throws Exception;
Pedro Liberal Fernandez45bddab2017-01-11 13:31:14 +0000496 }
497
498 private void runComplexOrderTest(
499 MergeStrategy strategy, List<String> preOrder, List<String> postOrder) throws Exception {
500 Map<Order, List<String>> expected = createExpectedMap(preOrder, postOrder);
501 for (Order order : Order.values()) {
Googlerd21a0d12019-11-21 13:52:30 -0800502 Depset union = strategy.merge(makeFourSets(order));
Pedro Liberal Fernandez45bddab2017-01-11 13:31:14 +0000503 assertThat(union.toCollection()).containsExactlyElementsIn(expected.get(order)).inOrder();
504 }
505 }
506
507 private Map<Order, List<String>> createExpectedMap(
508 List<String> preOrder, List<String> postOrder) {
509 Map<Order, List<String>> expected = new HashMap<>();
510
511 for (Order order : Order.values()) {
512 expected.put(order, isPostOrder(order) ? postOrder : preOrder);
513 }
514
515 return expected;
516 }
517
518 private boolean isPostOrder(Order order) {
519 return order == Order.STABLE_ORDER || order == Order.COMPILE_ORDER;
520 }
521
Googlerd21a0d12019-11-21 13:52:30 -0800522 private Depset[] makeFourSets(Order order) throws Exception {
523 return new Depset[] {
Googlerae586a02019-11-22 11:10:37 -0800524 Depset.legacyOf(order, Tuple.of("1", "11")),
525 Depset.legacyOf(order, Tuple.of("2", "22")),
526 Depset.legacyOf(order, Tuple.of("3", "33")),
527 Depset.legacyOf(order, Tuple.of("4", "44"))
janakr889f5622018-03-16 17:49:11 -0700528 };
Pedro Liberal Fernandez45bddab2017-01-11 13:31:14 +0000529 }
Ulf Adams89f012d2015-02-26 13:39:28 +0000530}