Lukacs Berki | 14328eb | 2015-10-21 10:47:26 +0000 | [diff] [blame] | 1 | // Copyright 2006 The Bazel Authors. All Rights Reserved. |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 2 | // |
| 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. |
| 14 | |
| 15 | package com.google.devtools.build.lib.syntax; |
| 16 | |
Ulf Adams | 795895a | 2015-03-06 15:58:35 +0000 | [diff] [blame] | 17 | import static com.google.common.truth.Truth.assertThat; |
cushon | 978cb00 | 2018-02-24 14:05:37 -0800 | [diff] [blame] | 18 | import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows; |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 19 | import static org.junit.Assert.fail; |
| 20 | |
brandjon | 2c98fff | 2018-02-06 01:32:46 -0800 | [diff] [blame] | 21 | import com.google.common.collect.ImmutableMap; |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 22 | import com.google.common.collect.Sets; |
brandjon | 2c98fff | 2018-02-06 01:32:46 -0800 | [diff] [blame] | 23 | import com.google.devtools.build.lib.syntax.Environment.Extension; |
Han-Wen Nienhuys | ceae8c5 | 2015-09-22 16:24:45 +0000 | [diff] [blame] | 24 | import com.google.devtools.build.lib.syntax.util.EvaluationTestCase; |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 25 | import org.junit.Test; |
| 26 | import org.junit.runner.RunWith; |
| 27 | import org.junit.runners.JUnit4; |
| 28 | |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 29 | /** |
| 30 | * Tests of Environment. |
| 31 | */ |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 32 | @RunWith(JUnit4.class) |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 33 | public class EnvironmentTest extends EvaluationTestCase { |
| 34 | |
| 35 | @Override |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 36 | public Environment newEnvironment() { |
| 37 | return newBuildEnvironment(); |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 38 | } |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 39 | |
| 40 | // Test the API directly |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 41 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 42 | public void testLookupAndUpdate() throws Exception { |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 43 | assertThat(lookup("foo")).isNull(); |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 44 | update("foo", "bar"); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 45 | assertThat(lookup("foo")).isEqualTo("bar"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 46 | } |
| 47 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 48 | @Test |
Laurent Le Brun | 1afb0b2 | 2016-10-26 12:46:42 +0000 | [diff] [blame] | 49 | public void testHasVariable() throws Exception { |
| 50 | assertThat(getEnvironment().hasVariable("VERSION")).isFalse(); |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 51 | update("VERSION", 42); |
Laurent Le Brun | 1afb0b2 | 2016-10-26 12:46:42 +0000 | [diff] [blame] | 52 | assertThat(getEnvironment().hasVariable("VERSION")).isTrue(); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 53 | } |
| 54 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 55 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 56 | public void testDoubleUpdateSucceeds() throws Exception { |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 57 | update("VERSION", 42); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 58 | assertThat(lookup("VERSION")).isEqualTo(42); |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 59 | update("VERSION", 43); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 60 | assertThat(lookup("VERSION")).isEqualTo(43); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 61 | } |
| 62 | |
| 63 | // Test assign through interpreter, lookup through API: |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 64 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 65 | public void testAssign() throws Exception { |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 66 | assertThat(lookup("foo")).isNull(); |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 67 | eval("foo = 'bar'"); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 68 | assertThat(lookup("foo")).isEqualTo("bar"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 69 | } |
| 70 | |
| 71 | // Test update through API, reference through interpreter: |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 72 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 73 | public void testReference() throws Exception { |
Laurent Le Brun | a6d8fe4 | 2016-11-28 18:14:54 +0000 | [diff] [blame] | 74 | setFailFast(false); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 75 | try { |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 76 | eval("foo"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 77 | fail(); |
| 78 | } catch (EvalException e) { |
Ulf Adams | 795895a | 2015-03-06 15:58:35 +0000 | [diff] [blame] | 79 | assertThat(e).hasMessage("name 'foo' is not defined"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 80 | } |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 81 | update("foo", "bar"); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 82 | assertThat(eval("foo")).isEqualTo("bar"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 83 | } |
| 84 | |
| 85 | // Test assign and reference through interpreter: |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 86 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 87 | public void testAssignAndReference() throws Exception { |
Laurent Le Brun | a6d8fe4 | 2016-11-28 18:14:54 +0000 | [diff] [blame] | 88 | setFailFast(false); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 89 | try { |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 90 | eval("foo"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 91 | fail(); |
| 92 | } catch (EvalException e) { |
Ulf Adams | 795895a | 2015-03-06 15:58:35 +0000 | [diff] [blame] | 93 | assertThat(e).hasMessage("name 'foo' is not defined"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 94 | } |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 95 | eval("foo = 'bar'"); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 96 | assertThat(eval("foo")).isEqualTo("bar"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 97 | } |
| 98 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 99 | @Test |
brandjon | b368b39 | 2017-10-20 22:02:02 +0200 | [diff] [blame] | 100 | public void testBuilderRequiresSemantics() throws Exception { |
| 101 | try (Mutability mut = Mutability.create("test")) { |
| 102 | IllegalArgumentException expected = |
cushon | 978cb00 | 2018-02-24 14:05:37 -0800 | [diff] [blame] | 103 | assertThrows(IllegalArgumentException.class, () -> Environment.builder(mut).build()); |
brandjon | b368b39 | 2017-10-20 22:02:02 +0200 | [diff] [blame] | 104 | assertThat(expected).hasMessageThat() |
| 105 | .contains("must call either setSemantics or useDefaultSemantics"); |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 110 | public void testGetVariableNames() throws Exception { |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 111 | Environment outerEnv; |
| 112 | Environment innerEnv; |
| 113 | try (Mutability mut = Mutability.create("outer")) { |
Laurent Le Brun | 5e99198 | 2016-10-14 13:39:45 +0000 | [diff] [blame] | 114 | outerEnv = |
| 115 | Environment.builder(mut) |
brandjon | 10a6b77 | 2017-10-20 20:48:30 +0200 | [diff] [blame] | 116 | .useDefaultSemantics() |
Laurent Le Brun | 5e99198 | 2016-10-14 13:39:45 +0000 | [diff] [blame] | 117 | .setGlobals(Environment.DEFAULT_GLOBALS) |
| 118 | .build() |
| 119 | .update("foo", "bar") |
| 120 | .update("wiz", 3); |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 121 | } |
| 122 | try (Mutability mut = Mutability.create("inner")) { |
| 123 | innerEnv = Environment.builder(mut) |
brandjon | 10a6b77 | 2017-10-20 20:48:30 +0200 | [diff] [blame] | 124 | .useDefaultSemantics() |
| 125 | .setGlobals(outerEnv.getGlobals()) |
| 126 | .build() |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 127 | .update("foo", "bat") |
| 128 | .update("quux", 42); |
| 129 | } |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 130 | |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 131 | assertThat(outerEnv.getVariableNames()) |
| 132 | .isEqualTo( |
| 133 | Sets.newHashSet( |
| 134 | "foo", |
| 135 | "wiz", |
| 136 | "False", |
| 137 | "None", |
| 138 | "True", |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 139 | "all", |
| 140 | "any", |
| 141 | "bool", |
| 142 | "dict", |
| 143 | "dir", |
| 144 | "enumerate", |
| 145 | "fail", |
| 146 | "getattr", |
| 147 | "hasattr", |
| 148 | "hash", |
| 149 | "int", |
| 150 | "len", |
| 151 | "list", |
| 152 | "max", |
| 153 | "min", |
| 154 | "print", |
| 155 | "range", |
| 156 | "repr", |
| 157 | "reversed", |
| 158 | "sorted", |
| 159 | "str", |
| 160 | "tuple", |
| 161 | "zip")); |
| 162 | assertThat(innerEnv.getVariableNames()) |
| 163 | .isEqualTo( |
| 164 | Sets.newHashSet( |
| 165 | "foo", |
| 166 | "wiz", |
| 167 | "quux", |
| 168 | "False", |
| 169 | "None", |
| 170 | "True", |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 171 | "all", |
| 172 | "any", |
| 173 | "bool", |
| 174 | "dict", |
| 175 | "dir", |
| 176 | "enumerate", |
| 177 | "fail", |
| 178 | "getattr", |
| 179 | "hasattr", |
| 180 | "hash", |
| 181 | "int", |
| 182 | "len", |
| 183 | "list", |
| 184 | "max", |
| 185 | "min", |
| 186 | "print", |
| 187 | "range", |
| 188 | "repr", |
| 189 | "reversed", |
| 190 | "sorted", |
| 191 | "str", |
| 192 | "tuple", |
| 193 | "zip")); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 194 | } |
| 195 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 196 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 197 | public void testToString() throws Exception { |
Michajlo Matijkiw | 8c539ea | 2017-02-22 23:02:46 +0000 | [diff] [blame] | 198 | update("subject", new StringLiteral("Hello, 'world'.")); |
| 199 | update("from", new StringLiteral("Java")); |
Francois-Rene Rideau | bd0c7bb | 2015-09-21 16:54:19 +0000 | [diff] [blame] | 200 | assertThat(getEnvironment().toString()).isEqualTo("<Environment[test]>"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 201 | } |
| 202 | |
Han-Wen Nienhuys | ccf19ea | 2015-02-27 15:53:24 +0000 | [diff] [blame] | 203 | @Test |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 204 | public void testBindToNullThrowsException() throws Exception { |
| 205 | try { |
Francois-Rene Rideau | 5f3e30c | 2015-04-10 19:08:39 +0000 | [diff] [blame] | 206 | update("some_name", null); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 207 | fail(); |
| 208 | } catch (NullPointerException e) { |
Ulf Adams | 795895a | 2015-03-06 15:58:35 +0000 | [diff] [blame] | 209 | assertThat(e).hasMessage("update(value == null)"); |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 210 | } |
| 211 | } |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 212 | |
| 213 | @Test |
| 214 | public void testFrozen() throws Exception { |
| 215 | Environment env; |
| 216 | try (Mutability mutability = Mutability.create("testFrozen")) { |
Laurent Le Brun | 5e99198 | 2016-10-14 13:39:45 +0000 | [diff] [blame] | 217 | env = |
| 218 | Environment.builder(mutability) |
brandjon | 10a6b77 | 2017-10-20 20:48:30 +0200 | [diff] [blame] | 219 | .useDefaultSemantics() |
Laurent Le Brun | 5e99198 | 2016-10-14 13:39:45 +0000 | [diff] [blame] | 220 | .setGlobals(Environment.DEFAULT_GLOBALS) |
| 221 | .setEventHandler(Environment.FAIL_FAST_HANDLER) |
| 222 | .build(); |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 223 | env.update("x", 1); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 224 | assertThat(env.lookup("x")).isEqualTo(1); |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 225 | env.update("y", 2); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 226 | assertThat(env.lookup("y")).isEqualTo(2); |
| 227 | assertThat(env.lookup("x")).isEqualTo(1); |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 228 | env.update("x", 3); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 229 | assertThat(env.lookup("x")).isEqualTo(3); |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 230 | } |
| 231 | try { |
| 232 | // This update to an existing variable should fail because the environment was frozen. |
| 233 | env.update("x", 4); |
| 234 | throw new Exception("failed to fail"); // not an AssertionError like fail() |
| 235 | } catch (AssertionError e) { |
| 236 | assertThat(e).hasMessage("Can't update x to 4 in frozen environment"); |
| 237 | } |
| 238 | try { |
| 239 | // This update to a new variable should also fail because the environment was frozen. |
| 240 | env.update("newvar", 5); |
| 241 | throw new Exception("failed to fail"); // not an AssertionError like fail() |
| 242 | } catch (AssertionError e) { |
| 243 | assertThat(e).hasMessage("Can't update newvar to 5 in frozen environment"); |
| 244 | } |
| 245 | } |
| 246 | |
| 247 | @Test |
| 248 | public void testReadOnly() throws Exception { |
| 249 | Environment env = newSkylarkEnvironment() |
| 250 | .setup("special_var", 42) |
| 251 | .update("global_var", 666); |
| 252 | |
| 253 | // We don't even get a runtime exception trying to modify these, |
| 254 | // because we get compile-time exceptions even before we reach runtime! |
| 255 | try { |
Laurent Le Brun | a6d8fe4 | 2016-11-28 18:14:54 +0000 | [diff] [blame] | 256 | BuildFileAST.eval(env, "special_var = 41"); |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 257 | throw new AssertionError("failed to fail"); |
Laurent Le Brun | d4d7fca | 2017-02-14 19:12:02 +0000 | [diff] [blame] | 258 | } catch (EvalException e) { |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 259 | assertThat(e).hasMessageThat().contains("Variable special_var is read only"); |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 260 | } |
| 261 | |
| 262 | try { |
Laurent Le Brun | a6d8fe4 | 2016-11-28 18:14:54 +0000 | [diff] [blame] | 263 | BuildFileAST.eval(env, "def foo(x): x += global_var; global_var = 36; return x", "foo(1)"); |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 264 | throw new AssertionError("failed to fail"); |
| 265 | } catch (EvalExceptionWithStackTrace e) { |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 266 | assertThat(e) |
| 267 | .hasMessageThat() |
| 268 | .contains( |
| 269 | "Variable 'global_var' is referenced before assignment. " |
| 270 | + "The variable is defined in the global scope."); |
Francois-Rene Rideau | 89312fb | 2015-09-10 18:53:03 +0000 | [diff] [blame] | 271 | } |
| 272 | } |
brandjon | 2c98fff | 2018-02-06 01:32:46 -0800 | [diff] [blame] | 273 | |
| 274 | @Test |
brandjon | 73e768e | 2018-02-13 12:26:52 -0800 | [diff] [blame] | 275 | public void testVarOrderDeterminism() throws Exception { |
| 276 | Mutability parentMutability = Mutability.create("parent env"); |
| 277 | Environment parentEnv = Environment.builder(parentMutability) |
| 278 | .useDefaultSemantics() |
| 279 | .build(); |
| 280 | parentEnv.update("a", 1); |
| 281 | parentEnv.update("c", 2); |
| 282 | parentEnv.update("b", 3); |
nharmata | 68cc06b | 2018-03-01 10:21:57 -0800 | [diff] [blame] | 283 | Environment.GlobalFrame parentFrame = parentEnv.getGlobals(); |
brandjon | 73e768e | 2018-02-13 12:26:52 -0800 | [diff] [blame] | 284 | parentMutability.freeze(); |
| 285 | Mutability mutability = Mutability.create("testing"); |
| 286 | Environment env = Environment.builder(mutability) |
| 287 | .useDefaultSemantics() |
| 288 | .setGlobals(parentFrame) |
| 289 | .build(); |
| 290 | env.update("x", 4); |
| 291 | env.update("z", 5); |
| 292 | env.update("y", 6); |
| 293 | // The order just has to be deterministic, but for definiteness this test spells out the exact |
| 294 | // order returned by the implementation: parent frame before current environment, and bindings |
| 295 | // within a frame ordered by when they were added. |
| 296 | assertThat(env.getVariableNames()) |
| 297 | .containsExactly("a", "c", "b", "x", "z", "y").inOrder(); |
| 298 | assertThat(env.getGlobals().getTransitiveBindings()) |
| 299 | .containsExactly("a", 1, "c", 2, "b", 3, "x", 4, "z", 5, "y", 6).inOrder(); |
| 300 | } |
| 301 | |
| 302 | @Test |
| 303 | public void testTransitiveHashCodeDeterminism() throws Exception { |
| 304 | // As a proxy for determinism, test that changing the order of imports doesn't change the hash |
| 305 | // code (within any one execution). |
| 306 | Extension a = new Extension(ImmutableMap.of(), "a123"); |
| 307 | Extension b = new Extension(ImmutableMap.of(), "b456"); |
| 308 | Extension c = new Extension(ImmutableMap.of(), "c789"); |
| 309 | Environment env1 = Environment.builder(Mutability.create("testing1")) |
| 310 | .useDefaultSemantics() |
| 311 | .setImportedExtensions(ImmutableMap.of("a", a, "b", b, "c", c)) |
| 312 | .setFileContentHashCode("z") |
| 313 | .build(); |
| 314 | Environment env2 = Environment.builder(Mutability.create("testing2")) |
| 315 | .useDefaultSemantics() |
| 316 | .setImportedExtensions(ImmutableMap.of("c", c, "b", b, "a", a)) |
| 317 | .setFileContentHashCode("z") |
| 318 | .build(); |
| 319 | assertThat(env1.getTransitiveContentHashCode()).isEqualTo(env2.getTransitiveContentHashCode()); |
| 320 | } |
| 321 | |
| 322 | @Test |
brandjon | 2c98fff | 2018-02-06 01:32:46 -0800 | [diff] [blame] | 323 | public void testExtensionEqualityDebugging_RhsIsNull() { |
| 324 | assertCheckStateFailsWithMessage( |
| 325 | new Extension(ImmutableMap.of(), "abc"), |
| 326 | null, |
| 327 | "got a null"); |
| 328 | } |
| 329 | |
| 330 | @Test |
| 331 | public void testExtensionEqualityDebugging_RhsHasBadType() { |
| 332 | assertCheckStateFailsWithMessage( |
| 333 | new Extension(ImmutableMap.of(), "abc"), |
| 334 | 5, |
| 335 | "got a java.lang.Integer"); |
| 336 | } |
| 337 | |
| 338 | @Test |
| 339 | public void testExtensionEqualityDebugging_DifferentBindings() { |
| 340 | assertCheckStateFailsWithMessage( |
| 341 | new Extension(ImmutableMap.of("w", 1, "x", 2, "y", 3), "abc"), |
| 342 | new Extension(ImmutableMap.of("y", 3, "z", 4), "abc"), |
| 343 | "in this one but not given one: [w, x]; in given one but not this one: [z]"); |
| 344 | } |
| 345 | |
| 346 | @Test |
| 347 | public void testExtensionEqualityDebugging_DifferentValues() { |
| 348 | assertCheckStateFailsWithMessage( |
| 349 | new Extension(ImmutableMap.of("x", 1, "y", "foo", "z", true), "abc"), |
| 350 | new Extension(ImmutableMap.of("x", 2.0, "y", "foo", "z", false), "abc"), |
janakr | cfc3432 | 2018-03-26 11:10:08 -0700 | [diff] [blame^] | 351 | "bindings are unequal: x: this one has 1 (class java.lang.Integer, 1), but given one has " |
| 352 | + "2.0 (class java.lang.Double, 2.0); z: this one has True (class java.lang.Boolean, " |
| 353 | + "true), but given one has False (class java.lang.Boolean, false)"); |
brandjon | 2c98fff | 2018-02-06 01:32:46 -0800 | [diff] [blame] | 354 | } |
| 355 | |
| 356 | @Test |
| 357 | public void testExtensionEqualityDebugging_DifferentHashes() { |
| 358 | assertCheckStateFailsWithMessage( |
| 359 | new Extension(ImmutableMap.of(), "abc"), |
| 360 | new Extension(ImmutableMap.of(), "xyz"), |
| 361 | "transitive content hashes don't match: abc != xyz"); |
| 362 | } |
| 363 | |
| 364 | private static void assertCheckStateFailsWithMessage( |
| 365 | Extension left, Object right, String substring) { |
| 366 | IllegalStateException expected = |
cushon | 978cb00 | 2018-02-24 14:05:37 -0800 | [diff] [blame] | 367 | assertThrows(IllegalStateException.class, () -> left.checkStateEquals(right)); |
brandjon | 2c98fff | 2018-02-06 01:32:46 -0800 | [diff] [blame] | 368 | assertThat(expected).hasMessageThat().contains(substring); |
| 369 | } |
Ulf Adams | 89f012d | 2015-02-26 13:39:28 +0000 | [diff] [blame] | 370 | } |