diff options
author | 2016-08-05 08:38:26 +0000 | |
---|---|---|
committer | 2016-08-05 13:32:33 +0000 | |
commit | cdb6ef554397c1d3da7ee9921305f646bec5ae16 (patch) | |
tree | 23cde8c143ecf6496570bf56ace1c6f405acbd35 /src/test/java/com/google/devtools/build/lib/skylark | |
parent | 6df3e71eb05493fa421121fa73e607a6fbf458c3 (diff) |
Make SkylarkClassObject "Bazel-specific".
This in preparation to DeclaredProviders implementation.
--
MOS_MIGRATED_REVID=129420617
Diffstat (limited to 'src/test/java/com/google/devtools/build/lib/skylark')
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java | 220 | ||||
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/skylark/util/SkylarkTestCase.java | 1 |
2 files changed, 220 insertions, 1 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java index 65d0c48ab0..07a8c6b232 100644 --- a/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java +++ b/src/test/java/com/google/devtools/build/lib/skylark/SkylarkRuleClassFunctionsTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertTrue; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.devtools.build.lib.cmdline.Label; @@ -33,15 +34,23 @@ import com.google.devtools.build.lib.packages.PredicateWithMessage; import com.google.devtools.build.lib.packages.RuleClass; import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; import com.google.devtools.build.lib.packages.SkylarkAspect; +import com.google.devtools.build.lib.packages.SkylarkClassObject; import com.google.devtools.build.lib.rules.SkylarkAttr; import com.google.devtools.build.lib.rules.SkylarkFileType; import com.google.devtools.build.lib.rules.SkylarkRuleClassFunctions; import com.google.devtools.build.lib.rules.SkylarkRuleClassFunctions.RuleFunction; import com.google.devtools.build.lib.skylark.util.SkylarkTestCase; +import com.google.devtools.build.lib.syntax.ClassObject; +import com.google.devtools.build.lib.syntax.Environment; import com.google.devtools.build.lib.syntax.EvalException; +import com.google.devtools.build.lib.syntax.EvalUtils; +import com.google.devtools.build.lib.syntax.SkylarkDict; +import com.google.devtools.build.lib.syntax.SkylarkList.MutableList; +import com.google.devtools.build.lib.syntax.SkylarkList.Tuple; +import com.google.devtools.build.lib.syntax.SkylarkNestedSet; import com.google.devtools.build.lib.syntax.Type; import com.google.devtools.build.lib.util.FileTypeSet; - +import java.util.Collection; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -748,4 +757,213 @@ public class SkylarkRuleClassFunctionsTest extends SkylarkTestCase { // Should succeed without a "licenses attribute is potentially configurable" loading error: createRuleContext("//third_party/foo:r"); } + + @Test + public void testStructCreation() throws Exception { + // TODO(fwe): cannot be handled by current testing suite + eval("x = struct(a = 1, b = 2)"); + assertThat(lookup("x")).isInstanceOf(ClassObject.class); + } + + @Test + public void testStructFields() throws Exception { + // TODO(fwe): cannot be handled by current testing suite + eval("x = struct(a = 1, b = 2)"); + ClassObject x = (ClassObject) lookup("x"); + assertEquals(1, x.getValue("a")); + assertEquals(2, x.getValue("b")); + } + + @Test + public void testStructAccessingFieldsFromSkylark() throws Exception { + eval("x = struct(a = 1, b = 2)", "x1 = x.a", "x2 = x.b"); + assertThat(lookup("x1")).isEqualTo(1); + assertThat(lookup("x2")).isEqualTo(2); + } + + @Test + public void testStructAccessingUnknownField() throws Exception { + checkErrorContains( + "'struct' object has no attribute 'c'\n" + "Available attributes: a, b", + "x = struct(a = 1, b = 2)", + "y = x.c"); + } + + @Test + public void testStructAccessingUnknownFieldWithArgs() throws Exception { + checkErrorContains( + "struct has no method 'c'", "x = struct(a = 1, b = 2)", "y = x.c()"); + } + + @Test + public void testStructAccessingNonFunctionFieldWithArgs() throws Exception { + checkErrorContains( + "struct field 'a' is not a function", "x = struct(a = 1, b = 2)", "x1 = x.a(1)"); + } + + @Test + public void testStructAccessingFunctionFieldWithArgs() throws Exception { + eval("def f(x): return x+5", "x = struct(a = f, b = 2)", "x1 = x.a(1)"); + assertThat(lookup("x1")).isEqualTo(6); + } + + @Test + public void testStructPosArgs() throws Exception { + checkErrorContains( + "struct(**kwargs) does not accept positional arguments, but got 1", "x = struct(1, b = 2)"); + } + + @Test + public void testStructConcatenationFieldNames() throws Exception { + // TODO(fwe): cannot be handled by current testing suite + eval("x = struct(a = 1, b = 2)", + "y = struct(c = 1, d = 2)", + "z = x + y\n"); + SkylarkClassObject z = (SkylarkClassObject) lookup("z"); + assertEquals(ImmutableSet.of("a", "b", "c", "d"), z.getKeys()); + } + + @Test + public void testStructConcatenationFieldValues() throws Exception { + // TODO(fwe): cannot be handled by current testing suite + eval("x = struct(a = 1, b = 2)", + "y = struct(c = 1, d = 2)", + "z = x + y\n"); + SkylarkClassObject z = (SkylarkClassObject) lookup("z"); + assertEquals(1, z.getValue("a")); + assertEquals(2, z.getValue("b")); + assertEquals(1, z.getValue("c")); + assertEquals(2, z.getValue("d")); + } + + @Test + public void testStructConcatenationCommonFields() throws Exception { + checkErrorContains("Cannot concat structs with common field(s): a", + "x = struct(a = 1, b = 2)", "y = struct(c = 1, a = 2)", "z = x + y\n"); + } + + @Test + public void testConditionalStructConcatenation() throws Exception { + // TODO(fwe): cannot be handled by current testing suite + eval("def func():", + " x = struct(a = 1, b = 2)", + " if True:", + " x += struct(c = 1, d = 2)", + " return x", + "x = func()"); + SkylarkClassObject x = (SkylarkClassObject) lookup("x"); + assertEquals(1, x.getValue("a")); + assertEquals(2, x.getValue("b")); + assertEquals(1, x.getValue("c")); + assertEquals(2, x.getValue("d")); + } + + @Test + public void testGetattrNoAttr() throws Exception { + checkErrorContains("Object of type 'struct' has no attribute \"b\"", + "s = struct(a='val')", "getattr(s, 'b')"); + } + + @Test + public void testGetattr() throws Exception { + eval( + "s = struct(a='val')", + "x = getattr(s, 'a')", + "y = getattr(s, 'b', 'def')", + "z = getattr(s, 'b', default = 'def')", + "w = getattr(s, 'a', default='ignored')"); + assertThat(lookup("x")).isEqualTo("val"); + assertThat(lookup("y")).isEqualTo("def"); + assertThat(lookup("z")).isEqualTo("def"); + assertThat(lookup("w")).isEqualTo("val"); + } + + @Test + public void testHasattr() throws Exception { + eval("s = struct(a=1)", + "x = hasattr(s, 'a')", + "y = hasattr(s, 'b')\n"); + assertThat(lookup("x")).isEqualTo(true); + assertThat(lookup("y")).isEqualTo(false); + } + + @Test + public void testStructStr() throws Exception { + assertThat(eval("str(struct(x = 2, y = 3, z = 4))")) + .isEqualTo("struct(x = 2, y = 3, z = 4)"); + } + + @Test + public void testStructsInSets() throws Exception { + eval("set([struct(a='a')])"); + } + + @Test + public void testStructMembersAreImmutable() throws Exception { + checkErrorContains( + "can only assign to variables and tuples, not to 's.x'", + "s = struct(x = 'a')", + "s.x = 'b'\n"); + } + + @Test + public void testStructDictMembersAreImmutable() throws Exception { + checkErrorContains( + "can only assign to variables and tuples, not to 's.x['b']'", + "s = struct(x = {'a' : 1})", + "s.x['b'] = 2\n"); + } + + @Test + public void testNsetGoodCompositeItem() throws Exception { + eval("def func():", + " return set([struct(a='a')])", + "s = func()"); + Collection<Object> result = ((SkylarkNestedSet) lookup("s")).toCollection(); + assertThat(result).hasSize(1); + assertThat(result.iterator().next()).isInstanceOf(SkylarkClassObject.class); + } + + @Test + public void testNsetBadMutableItem() throws Exception { + checkEvalError("sets cannot contain mutable items", "set([([],)])"); + checkEvalError("sets cannot contain mutable items", "set([struct(a=[])])"); + } + + private static SkylarkClassObject makeStruct(String field, Object value) { + return new SkylarkClassObject(ImmutableMap.of(field, value)); + } + + private static SkylarkClassObject makeBigStruct(Environment env) { + // struct(a=[struct(x={1:1}), ()], b=(), c={2:2}) + return new SkylarkClassObject(ImmutableMap.<String, Object>of( + "a", MutableList.<Object>of(env, + new SkylarkClassObject(ImmutableMap.<String, Object>of( + "x", SkylarkDict.<Object, Object>of(env, 1, 1))), + Tuple.of()), + "b", Tuple.of(), + "c", SkylarkDict.<Object, Object>of(env, 2, 2))); + } + + @Test + public void testStructMutabilityShallow() throws Exception { + assertTrue(EvalUtils.isImmutable(makeStruct("a", 1))); + } + + private static MutableList<Object> makeList(Environment env) { + return MutableList.<Object>of(env, 1, 2, 3); + } + + + @Test + public void testStructMutabilityDeep() throws Exception { + assertTrue(EvalUtils.isImmutable(Tuple.<Object>of(makeList(null)))); + assertTrue(EvalUtils.isImmutable(makeStruct("a", makeList(null)))); + assertTrue(EvalUtils.isImmutable(makeBigStruct(null))); + + assertFalse(EvalUtils.isImmutable(Tuple.<Object>of(makeList(ev.getEnvironment())))); + assertFalse(EvalUtils.isImmutable(makeStruct("a", makeList(ev.getEnvironment())))); + assertFalse(EvalUtils.isImmutable(makeBigStruct(ev.getEnvironment()))); + } + } diff --git a/src/test/java/com/google/devtools/build/lib/skylark/util/SkylarkTestCase.java b/src/test/java/com/google/devtools/build/lib/skylark/util/SkylarkTestCase.java index cf17c9dbb3..5efd8a8209 100644 --- a/src/test/java/com/google/devtools/build/lib/skylark/util/SkylarkTestCase.java +++ b/src/test/java/com/google/devtools/build/lib/skylark/util/SkylarkTestCase.java @@ -149,6 +149,7 @@ public abstract class SkylarkTestCase extends BuildViewTestCase { } protected void checkErrorContains(String errorMsg, String... lines) throws Exception { + ev.setFailFast(false); try { eval(lines); fail("checkErrorContains(String, String...): There was no error"); |