aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test/java/com/google/devtools/build/lib/skylark
diff options
context:
space:
mode:
authorGravatar Dmitry Lomov <dslomov@google.com>2016-08-05 08:38:26 +0000
committerGravatar Yun Peng <pcloudy@google.com>2016-08-05 13:32:33 +0000
commitcdb6ef554397c1d3da7ee9921305f646bec5ae16 (patch)
tree23cde8c143ecf6496570bf56ace1c6f405acbd35 /src/test/java/com/google/devtools/build/lib/skylark
parent6df3e71eb05493fa421121fa73e607a6fbf458c3 (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.java220
-rw-r--r--src/test/java/com/google/devtools/build/lib/skylark/util/SkylarkTestCase.java1
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");