aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar laurentlb <laurentlb@google.com>2018-03-28 13:27:12 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-03-28 13:28:34 -0700
commitab0ada9ebbc63785fe6ceb80a5be2a44bee6eef5 (patch)
treed491c813c15255af44017d407e1c80d2ced7cbd8
parentc45e182028c75bb78b7a12cb5cb3ca93c6b82c4a (diff)
Move more tests to test suite (int function, list index, list mutation)
RELNOTES: None. PiperOrigin-RevId: 190823566
-rw-r--r--src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java251
-rw-r--r--src/test/skylark/skylark_test.py22
-rw-r--r--src/test/skylark/testdata/int_function.sky95
-rw-r--r--src/test/skylark/testdata/list_mutation.sky87
-rw-r--r--src/test/skylark/testdata/list_slices.sky22
-rw-r--r--src/test/skylark/testdata/range.sky18
-rw-r--r--src/test/skylark/testdata/reversed.sky30
7 files changed, 263 insertions, 262 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
index 7c63e18feb..2c353d6fc9 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/MethodLibraryTest.java
@@ -17,7 +17,6 @@ package com.google.devtools.build.lib.syntax;
import static com.google.common.truth.Truth.assertThat;
import com.google.common.collect.Iterables;
-import com.google.devtools.build.lib.syntax.SkylarkList.MutableList;
import com.google.devtools.build.lib.syntax.util.EvaluationTestCase;
import org.junit.Before;
import org.junit.Test;
@@ -206,51 +205,6 @@ public class MethodLibraryTest extends EvaluationTestCase {
}
@Test
- public void testReversedWithInvalidTypes() throws Exception {
- new BothModesTest()
- .testIfExactError("type 'NoneType' is not iterable", "reversed(None)")
- .testIfExactError("type 'int' is not iterable", "reversed(1)")
- .testIfExactError(
- "Argument to reversed() must be a sequence, not a dictionary.", "reversed({1: 3})");
- new SkylarkTest()
- .testIfExactError(
- "Argument to reversed() must be a sequence, not a depset.", "reversed(depset([1]))");
- }
-
- @Test
- public void testReversedWithLists() throws Exception {
- new BothModesTest()
- .testEval("reversed([])", "[]")
- .testEval("reversed([1])", "[1]")
- .testEval("reversed([1, 2, 3, 4, 5])", "[5, 4, 3, 2, 1]")
- .testEval("reversed([[1, 2], 3, 4, [5]])", "[[5], 4, 3, [1, 2]]")
- .testEval("reversed([1, 1, 1, 1, 2])", "[2, 1, 1, 1, 1]");
- }
-
- @Test
- public void testReversedNoSideEffects() throws Exception {
- new SkylarkTest()
- .testEval(
- "def foo():\n"
- + " x = ['a', 'b']\n"
- + " y = reversed(x)\n"
- + " y += ['c']\n"
- + " return x\n"
- + "foo()",
- "['a', 'b']");
- }
-
- @Test
- public void testEquivalenceOfReversedAndSlice() throws Exception {
- String[] data = new String[] {"[]", "[1]", "[1, 2, 3]"};
- for (String toBeReversed : data) {
- new BothModesTest()
- .testEval(
- String.format("reversed(%s)", toBeReversed), String.format("%s[::-1]", toBeReversed));
- }
- }
-
- @Test
public void testListSort() throws Exception {
new BothModesTest()
.testEval("sorted([0,1,2,3])", "[0, 1, 2, 3]")
@@ -286,12 +240,6 @@ public class MethodLibraryTest extends EvaluationTestCase {
}
@Test
- public void testListAccessBadIndex() throws Exception {
- new BothModesTest()
- .testIfErrorContains("indices must be integers, not string", "[[1], [2]]['a']");
- }
-
- @Test
public void testDictionaryAccess() throws Exception {
new BothModesTest()
.testEval("{1: ['foo']}[1]", "['foo']")
@@ -475,34 +423,6 @@ public class MethodLibraryTest extends EvaluationTestCase {
}
@Test
- public void testListIndex() throws Exception {
- new BothModesTest()
- .testStatement("['a', 'b', 'c', 'd'][0]", "a")
- .testStatement("['a', 'b', 'c', 'd'][1]", "b")
- .testStatement("['a', 'b', 'c', 'd'][-1]", "d")
- .testStatement("['a', 'b', 'c', 'd'][-2]", "c")
- .testStatement("[0, 1, 2][-3]", 0)
- .testStatement("[0, 1, 2][-2]", 1)
- .testStatement("[0, 1, 2][-1]", 2)
- .testStatement("[0, 1, 2][0]", 0);
- }
-
- @Test
- public void testListIndexOutOfRange() throws Exception {
- new BothModesTest()
- .testIfErrorContains(
- "index out of range (index is 3, but sequence has 3 elements)", "[0, 1, 2][3]")
- .testIfErrorContains(
- "index out of range (index is -4, but sequence has 3 elements)", "[0, 1, 2][-4]")
- .testIfErrorContains(
- "index out of range (index is -2, but sequence has 1 elements)", "[0][-2]")
- .testIfErrorContains(
- "index out of range (index is 1, but sequence has 1 elements)", "[0][1]")
- .testIfErrorContains(
- "index out of range (index is 1, but sequence has 0 elements)", "[][1]");
- }
-
- @Test
public void testHash() throws Exception {
// We specify the same string hashing algorithm as String.hashCode().
new SkylarkTest()
@@ -554,80 +474,6 @@ public class MethodLibraryTest extends EvaluationTestCase {
}
@Test
- public void testPyListAppend() throws Exception {
- new BuildTest()
- .setUp("FOO = ['a', 'b']", "FOO.insert(0, 'c')")
- .testLookup("FOO", MutableList.of(env, "c", "a", "b"))
- .setUp("FOO.insert(1, 'd')")
- .testLookup("FOO", MutableList.of(env, "c", "d", "a", "b"))
- .setUp("FOO.insert(4, 'e')")
- .testLookup("FOO", MutableList.of(env, "c", "d", "a", "b", "e"))
- .setUp("FOO.insert(-10, 'f')")
- .testLookup("FOO", MutableList.of(env, "f", "c", "d", "a", "b", "e"))
- .setUp("FOO.insert(10, 'g')")
- .testLookup("FOO", MutableList.of(env, "f", "c", "d", "a", "b", "e", "g"))
- .testIfErrorContains("type 'tuple' has no method insert(int)", "(1, 2).insert(3)");
- }
-
- @Test
- public void testPyListInsert() throws Exception {
- new BuildTest()
- .setUp("FOO = ['a', 'b']", "FOO.append('c')")
- .testLookup("FOO", MutableList.of(env, "a", "b", "c"))
- .testIfErrorContains("type 'tuple' has no method append(int)", "(1, 2).append(3)");
- }
-
- @Test
- public void testPyListExtend() throws Exception {
- new BuildTest()
- .setUp("FOO = ['a', 'b']", "FOO.extend(['c', 'd'])", "FOO.extend(('e', 'f'))")
- .testLookup("FOO", MutableList.of(env, "a", "b", "c", "d", "e", "f"))
- .testIfErrorContains("type 'tuple' has no method extend(list)", "(1, 2).extend([3, 4])")
- .testIfErrorContains(
- "argument 'items' has type 'int', but should be 'sequence'\n"
- + "in call to builtin method list.extend(items)",
- "[1, 2].extend(3)");
- }
-
- @Test
- public void testListRemove() throws Exception {
- new BothModesTest()
- .setUp("foo = ['a', 'b', 'c', 'b']", "foo.remove('b')")
- .testLookup("foo", MutableList.of(env, "a", "c", "b"))
- .setUp("foo.remove('c')")
- .testLookup("foo", MutableList.of(env, "a", "b"))
- .setUp("foo.remove('a')")
- .testLookup("foo", MutableList.of(env, "b"))
- .setUp("foo.remove('b')")
- .testLookup("foo", MutableList.of(env))
- .testIfErrorContains("item 3 not found in list", "[1, 2].remove(3)");
-
- new BothModesTest()
- .testIfErrorContains("type 'tuple' has no method remove(int)", "(1, 2).remove(3)");
- }
-
- @Test
- public void testListPop() throws Exception {
- new BothModesTest()
- .setUp("li = [2, 3, 4]; ret = li.pop()")
- .testLookup("li", MutableList.of(env, 2, 3))
- .testLookup("ret", 4);
- new BothModesTest()
- .setUp("li = [2, 3, 4]; ret = li.pop(-2)")
- .testLookup("li", MutableList.of(env, 2, 4))
- .testLookup("ret", 3);
- new BothModesTest()
- .setUp("li = [2, 3, 4]; ret = li.pop(1)")
- .testLookup("li", MutableList.of(env, 2, 4))
- .testLookup("ret", 3);
- new BothModesTest()
- .testIfErrorContains(
- "index out of range (index is 3, but sequence has 2 elements)", "[1, 2].pop(3)");
-
- new BothModesTest().testIfErrorContains("type 'tuple' has no method pop()", "(1, 2).pop()");
- }
-
- @Test
public void testReassignmentOfPrimitivesNotForbiddenByCoreLanguage() throws Exception {
new BuildTest()
.setUp("cc_binary = (['hello.cc'])")
@@ -686,103 +532,6 @@ public class MethodLibraryTest extends EvaluationTestCase {
}
@Test
- public void testIntNonstring() throws Exception {
- new BothModesTest()
- .testStatement("int(0)", 0)
- .testStatement("int(42)", 42)
- .testStatement("int(-1)", -1)
- .testStatement("int(2147483647)", 2147483647)
- // TODO(bazel-team): -2147483648 is not actually a valid int literal even though it's a
- // valid int value, hence the -1 expression.
- .testStatement("int(-2147483647 - 1)", -2147483648)
- .testStatement("int(True)", 1)
- .testStatement("int(False)", 0)
- .testIfErrorContains("None is not of type string or int or bool", "int(None)")
- // This case is allowed in Python but not Skylark.
- .testIfErrorContains("insufficient arguments received", "int()");
- }
-
- @Test
- public void testIntStringNoBase_Simple() throws Exception {
- // Includes same numbers as integer test cases above.
- new BothModesTest()
- .testStatement("int('0')", 0)
- .testStatement("int('42')", 42)
- .testStatement("int('-1')", -1)
- .testStatement("int('2147483647')", 2147483647)
- .testStatement("int('-2147483648')", -2147483648)
- // Leading zero allowed when not using base = 0.
- .testStatement("int('016')", 16)
- // Leading plus sign allowed for strings.
- .testStatement("int('+42')", 42);
- }
-
- @Test
- public void testIntStringNoBase_BadStrings() throws Exception {
- new BothModesTest()
- .testIfErrorContains("invalid base-10 integer constant: 2147483648", "int(2147483648)")
- // .testIfErrorContains("invalid base-10 integer constant: -2147483649", "int(-2147483649)")
- .testIfErrorContains("cannot be empty", "int('')")
- // Surrounding whitespace is not allowed.
- .testIfErrorContains("invalid literal for int() with base 10: \" 42 \"", "int(' 42 ')")
- .testIfErrorContains("invalid literal for int() with base 10: \"-\"", "int('-')")
- .testIfErrorContains("invalid literal for int() with base 10: \"0x\"", "int('0x')")
- .testIfErrorContains("invalid literal for int() with base 10: \"1.5\"", "int('1.5')")
- .testIfErrorContains("invalid literal for int() with base 10: \"ab\"", "int('ab')");
- }
-
- @Test
- public void testIntStringWithBase() throws Exception {
- new BothModesTest()
- .testStatement("int('11', 2)", 3)
- .testStatement("int('-11', 2)", -3)
- .testStatement("int('11', 9)", 10)
- .testStatement("int('AF', 16)", 175)
- .testStatement("int('11', 36)", 37)
- .testStatement("int('az', 36)", 395)
- .testStatement("int('11', 10)", 11)
- .testStatement("int('11', 0)", 11)
- .testStatement("int('016', 8)", 14)
- .testStatement("int('016', 16)", 22);
- }
-
- @Test
- public void testIntStringWithBase_InvalidBase() throws Exception {
- new BothModesTest()
- .testIfErrorContains(
- "cannot infer base for int() when value begins with a 0: \"016\"",
- "int('016', 0)")
- .testIfExactError("invalid literal for int() with base 3: \"123\"", "int('123', 3)")
- .testIfExactError("invalid literal for int() with base 15: \"FF\"", "int('FF', 15)")
- .testIfExactError("int() base must be >= 2 and <= 36", "int('123', -1)")
- .testIfExactError("int() base must be >= 2 and <= 36", "int('123', 1)")
- .testIfExactError("int() base must be >= 2 and <= 36", "int('123', 37)");
- }
-
- @Test
- public void testIntStringWithBase_Prefix() throws Exception {
- new BothModesTest()
- .testStatement("int('0b11', 0)", 3)
- .testStatement("int('-0b11', 0)", -3)
- .testStatement("int('+0b11', 0)", 3)
- .testStatement("int('0B11', 2)", 3)
- .testStatement("int('0o11', 0)", 9)
- .testStatement("int('0O11', 8)", 9)
- .testStatement("int('0XFF', 0)", 255)
- .testStatement("int('0xFF', 16)", 255)
- .testIfExactError("invalid literal for int() with base 8: \"0xFF\"", "int('0xFF', 8)");
- }
-
- @Test
- public void testIntNonstringWithBase() throws Exception {
- new BothModesTest()
- .testIfExactError("int() can't convert non-string with explicit base", "int(True, 2)")
- .testIfExactError("int() can't convert non-string with explicit base", "int(1, 2)")
- .testIfExactError("int() can't convert non-string with explicit base", "int(True, 10)")
- ;
- }
-
- @Test
public void testStrFunction() throws Exception {
new SkylarkTest().testStatement("def foo(x): return x\nstr(foo)", "<function foo>");
}
diff --git a/src/test/skylark/skylark_test.py b/src/test/skylark/skylark_test.py
index 55bf92b7ec..0e7bcf5e48 100644
--- a/src/test/skylark/skylark_test.py
+++ b/src/test/skylark/skylark_test.py
@@ -34,6 +34,7 @@ class SkylarkTest(unittest.TestCase):
CHUNK_SEP = "---"
ERR_SEP = "###"
+ seen_error = False
def chunks(self, path):
code = []
@@ -61,21 +62,18 @@ class SkylarkTest(unittest.TestCase):
def check_output(self, output, expected):
if expected and not output:
- raise Exception("Expected error:", expected)
+ self.seen_error = True
+ print("Expected error:", expected)
if output and not expected:
- raise Exception("Unexpected error:", output)
+ self.seen_error = True
+ print("Unexpected error:", output)
for exp in expected:
- if not re.search(exp, output):
- raise Exception("Error `{}` not found, got: {}".format(exp, output))
-
- TESTS = [
- "int.sky",
- "equality.sky",
- "and_or_not.sky",
- "min_max.sky",
- ]
+ # Try both substring and regex matching.
+ if exp not in output and not re.search(exp, output):
+ self.seen_error = True
+ print("Error `{}` not found, got: `{}`".format(exp, output))
PRELUDE = """
def assert_eq(x, y):
@@ -100,6 +98,8 @@ def assert_(cond, msg="assertion failed"):
output = self.evaluate(tmp.name).decode("utf-8")
os.unlink(tmp.name)
self.check_output(output, expected)
+ if self.seen_error:
+ raise Exception("Test failed")
if __name__ == "__main__":
diff --git a/src/test/skylark/testdata/int_function.sky b/src/test/skylark/testdata/int_function.sky
new file mode 100644
index 0000000000..7d6a382a65
--- /dev/null
+++ b/src/test/skylark/testdata/int_function.sky
@@ -0,0 +1,95 @@
+# int
+assert_eq(int(0), 0)
+assert_eq(int(42), 42)
+assert_eq(int(-1), -1)
+assert_eq(int(2147483647), 2147483647)
+# -2147483648 is not actually a valid int literal even though it's a
+# valid int value, hence the -1 expression.
+assert_eq(int(-2147483647 - 1), -2147483647 - 1)
+assert_eq(int(True), 1)
+assert_eq(int(False), 0)
+
+---
+int(None) ### None is not of type string or int or bool
+---
+# This case is allowed in Python but not Skylark
+int() ### insufficient arguments received
+---
+
+# string, no base
+# Includes same numbers as integer test cases above.
+assert_eq(int('0'), 0)
+assert_eq(int('42'), 42)
+assert_eq(int('-1'), -1)
+assert_eq(int('2147483647'), 2147483647)
+assert_eq(int('-2147483648'), -2147483647 - 1)
+# Leading zero allowed when not using base = 0.
+assert_eq(int('016'), 16)
+# Leading plus sign allowed for strings.
+assert_eq(int('+42'), 42)
+
+---
+int(2147483648) ### invalid base-10 integer constant: 2147483648
+---
+int(-2147483649) ### invalid base-10 integer constant: 2147483649
+---
+int('') ### cannot be empty
+---
+# Surrounding whitespace is not allowed
+int(' 42 ') ### invalid literal for int() with base 10: " 42 "
+---
+int('-') ### invalid literal for int() with base 10: "-"
+---
+int('0x') ### invalid literal for int() with base 10: "0x"
+---
+int('1.5') ### invalid literal for int() with base 10: "1.5"
+---
+int('ab') ### invalid literal for int() with base 10: "ab"
+---
+
+assert_eq(int('11', 2), 3)
+assert_eq(int('-11', 2), -3)
+assert_eq(int('11', 9), 10)
+assert_eq(int('AF', 16), 175)
+assert_eq(int('11', 36), 37)
+assert_eq(int('az', 36), 395)
+assert_eq(int('11', 10), 11)
+assert_eq(int('11', 0), 11)
+assert_eq(int('016', 8), 14)
+assert_eq(int('016', 16), 22)
+
+---
+# invalid base
+int('016', 0) ### cannot infer base for int() when value begins with a 0: "016"
+---
+int('123', 3) ### invalid literal for int() with base 3: "123"
+---
+int('FF', 15) ### invalid literal for int() with base 15: "FF"
+---
+int('123', -1) ### int() base must be >= 2 and <= 36
+---
+int('123', 1) ### int() base must be >= 2 and <= 36
+---
+int('123', 37) ### int() base must be >= 2 and <= 36
+---
+int('123', 'x') ### base must be an integer (got 'string')
+---
+
+# base with prefix
+assert_eq(int('0b11', 0), 3)
+assert_eq(int('-0b11', 0), -3)
+assert_eq(int('+0b11', 0), 3)
+assert_eq(int('0B11', 2), 3)
+assert_eq(int('0o11', 0), 9)
+assert_eq(int('0O11', 8), 9)
+assert_eq(int('0XFF', 0), 255)
+assert_eq(int('0xFF', 16), 255)
+
+---
+int('0xFF', 8) ### invalid literal for int() with base 8: "0xFF"
+---
+int(True, 2) ### int() can't convert non-string with explicit base
+---
+int(1, 2) ### int() can't convert non-string with explicit base
+---
+int(True, 10) ### int() can't convert non-string with explicit base
diff --git a/src/test/skylark/testdata/list_mutation.sky b/src/test/skylark/testdata/list_mutation.sky
new file mode 100644
index 0000000000..24d5425952
--- /dev/null
+++ b/src/test/skylark/testdata/list_mutation.sky
@@ -0,0 +1,87 @@
+# insert
+
+foo = ['a', 'b']
+
+foo.insert(0, 'c')
+assert_eq(foo, ['c', 'a', 'b'])
+
+foo.insert(1, 'd')
+assert_eq(foo, ['c', 'd', 'a', 'b'])
+
+foo.insert(4, 'e')
+assert_eq(foo, ['c', 'd', 'a', 'b', 'e'])
+
+foo.insert(-10, 'f')
+assert_eq(foo, ['f', 'c', 'd', 'a', 'b', 'e'])
+
+foo.insert(10, 'g')
+assert_eq(foo, ['f', 'c', 'd', 'a', 'b', 'e', 'g'])
+
+---
+(1, 2).insert(3) ### type 'tuple' has no method insert\(int\)
+---
+
+# append
+
+foo = ['a', 'b']
+foo.append('c')
+assert_eq(foo, ['a', 'b', 'c'])
+foo.append('d')
+assert_eq(foo, ['a', 'b', 'c', 'd'])
+
+---
+(1, 2).append(3) ### type 'tuple' has no method append\(int\)
+---
+
+# extend
+
+foo = ['a', 'b']
+foo.extend(['c', 'd'])
+foo.extend(('e', 'f'))
+assert_eq(foo, ['a', 'b', 'c', 'd', 'e', 'f'])
+
+---
+(1, 2).extend([3, 4]) ### type 'tuple' has no method extend(list)
+---
+[1, 2].extend(3) ### argument 'items' has type 'int', but should be 'sequence'
+
+# remove
+
+foo = ['a', 'b', 'c', 'b']
+
+foo.remove('b')
+assert_eq(foo, ['a', 'c', 'b'])
+
+foo.remove('c')
+assert_eq(foo, ['a', 'b'])
+
+foo.remove('a')
+assert_eq(foo, ['b'])
+
+foo.remove('b')
+assert_eq(foo, [])
+
+---
+(1, 2).remove(3) ### type 'tuple' has no method remove\(int\)
+---
+[1, 2].remove(3) ### item 3 not found in list
+---
+
+# pop
+
+li1 = [2, 3, 4]
+assert_eq(li1.pop(), 4)
+assert_eq(li1, [2, 3])
+
+li2 = [2, 3, 4]
+assert_eq(li2.pop(-2), 3)
+assert_eq(li2, [2, 4])
+
+li3 = [2, 3, 4]
+assert_eq(li3.pop(1), 3)
+assert_eq(li3, [2, 4])
+
+---
+[1, 2].pop(3) ### index out of range (index is 3, but sequence has 2 elements)
+---
+(1, 2).pop() ### type 'tuple' has no method pop()
diff --git a/src/test/skylark/testdata/list_slices.sky b/src/test/skylark/testdata/list_slices.sky
index 3ec2999cba..b79661e23c 100644
--- a/src/test/skylark/testdata/list_slices.sky
+++ b/src/test/skylark/testdata/list_slices.sky
@@ -46,6 +46,16 @@ assert_eq((1, 2, 3, 4, 5)[3:1:-1], (4, 3))
assert_eq((1, 2, 3, 4, 5)[::-2], (5, 3, 1))
assert_eq((1, 2, 3, 4, 5)[::-10], (5,))
+# index
+assert_eq(['a', 'b', 'c', 'd'][0], 'a')
+assert_eq(['a', 'b', 'c', 'd'][1], 'b')
+assert_eq(['a', 'b', 'c', 'd'][-1], 'd')
+assert_eq(['a', 'b', 'c', 'd'][-2], 'c')
+assert_eq([0, 1, 2][-3], 0)
+assert_eq([0, 1, 2][-2], 1)
+assert_eq([0, 1, 2][-1], 2)
+assert_eq([0, 1, 2][0], 0)
+
---
'123'['a'::] ### slice start must be an integer, not 'a'
---
@@ -60,3 +70,15 @@ assert_eq((1, 2, 3, 4, 5)[::-10], (5,))
[1, 2, 3][:3:0] ### slice step cannot be zero
---
[1, 2, 3][1:3:0] ### slice step cannot be zero
+---
+[[1], [2]]['a'] ### indices must be integers, not string
+---
+[0, 1, 2][3] ### index out of range (index is 3, but sequence has 3 elements)
+---
+[0, 1, 2][-4] ### index out of range (index is -4, but sequence has 3 elements)
+---
+[0][-2] ### index out of range (index is -2, but sequence has 1 elements)
+---
+[0][1] ### index out of range (index is 1, but sequence has 1 elements)
+---
+[][1] ### index out of range (index is 1, but sequence has 0 elements)
diff --git a/src/test/skylark/testdata/range.sky b/src/test/skylark/testdata/range.sky
new file mode 100644
index 0000000000..75d9be441b
--- /dev/null
+++ b/src/test/skylark/testdata/range.sky
@@ -0,0 +1,18 @@
+assert_eq(range(5), [0, 1, 2, 3, 4])
+assert_eq(range(0), [])
+assert_eq(range(1), [0])
+assert_eq(range(-2), [])
+assert_eq(range(-3, 2), [-3, -2, -1, 0, 1])
+assert_eq(range(3, 2), [])
+assert_eq(range(3, 3), [])
+assert_eq(range(3, 4), [3])
+assert_eq(range(3, 5), [3, 4])
+assert_eq(range(-3, 5, 2), [-3, -1, 1, 3])
+assert_eq(range(-3, 6, 2), [-3, -1, 1, 3, 5])
+assert_eq(range(5, 0, -1), [5, 4, 3, 2, 1])
+assert_eq(range(5, 0, -10), [5])
+assert_eq(range(0, -3, -2), [0, -2])
+
+---
+range(2, 3, 0) ### step cannot be 0
+
diff --git a/src/test/skylark/testdata/reversed.sky b/src/test/skylark/testdata/reversed.sky
new file mode 100644
index 0000000000..91ce565687
--- /dev/null
+++ b/src/test/skylark/testdata/reversed.sky
@@ -0,0 +1,30 @@
+# lists
+
+assert_eq(reversed(''), [])
+assert_eq(reversed('a'), ['a'])
+assert_eq(reversed('abc'), ['c', 'b', 'a'])
+assert_eq(reversed('__test '), [' ', ' ', 't', 's', 'e', 't', '_', '_'])
+assert_eq(reversed('bbb'), ['b', 'b', 'b'])
+
+---
+reversed(None) ### type 'NoneType' is not iterable
+---
+reversed(1) ### type 'int' is not iterable
+---
+reversed({1: 3}) ### Argument to reversed() must be a sequence, not a dictionary
+---
+
+x = ['a', 'b']
+y = reversed(x)
+y.append('c')
+assert_eq(y, ['b', 'a', 'c'])
+assert_eq(x, ['a', 'b'])
+
+def reverse_equivalence(inp):
+ assert_eq(reversed(inp), inp[::-1])
+ assert_eq(reversed(reversed(inp)), inp)
+
+reverse_equivalence([])
+reverse_equivalence([1])
+reverse_equivalence(["a", "b"])
+