From 87a50319d795cc63dff6b8d0f718fcfc41a77255 Mon Sep 17 00:00:00 2001 From: Marwan Tammam Date: Sun, 2 Jun 2019 14:16:29 +0200 Subject: [PATCH] Implement test runner and add Java's test data Test cases that fail in 1 or more implementation due to inconsistencies are commented. --- test_suite/BUILD | 2 +- test_suite/starlark_test.py | 77 +++++++++ test_suite/testdata/empty.star | 0 test_suite/testdata/java/all_any.star | 43 +++++ test_suite/testdata/java/and_or_not.star | 43 +++++ test_suite/testdata/java/dict.star | 87 ++++++++++ test_suite/testdata/java/equality.star | 69 ++++++++ test_suite/testdata/java/int.star | 66 ++++++++ test_suite/testdata/java/int_constructor.star | 44 +++++ test_suite/testdata/java/int_function.star | 97 +++++++++++ test_suite/testdata/java/list_mutation.star | 90 ++++++++++ test_suite/testdata/java/list_slices.star | 84 ++++++++++ test_suite/testdata/java/min_max.star | 53 ++++++ test_suite/testdata/java/range.star | 17 ++ test_suite/testdata/java/reversed.star | 32 ++++ test_suite/testdata/java/string_elems.star | 15 ++ test_suite/testdata/java/string_find.star | 31 ++++ test_suite/testdata/java/string_format.star | 94 +++++++++++ test_suite/testdata/java/string_misc.star | 156 ++++++++++++++++++ .../testdata/java/string_partition.star | 41 +++++ .../testdata/java/string_slice_index.star | 60 +++++++ test_suite/testdata/java/string_split.star | 45 +++++ .../testdata/java/string_splitlines.star | 33 ++++ .../testdata/java/string_test_characters.star | 54 ++++++ 24 files changed, 1332 insertions(+), 1 deletion(-) delete mode 100644 test_suite/testdata/empty.star create mode 100644 test_suite/testdata/java/all_any.star create mode 100644 test_suite/testdata/java/and_or_not.star create mode 100644 test_suite/testdata/java/dict.star create mode 100644 test_suite/testdata/java/equality.star create mode 100644 test_suite/testdata/java/int.star create mode 100644 test_suite/testdata/java/int_constructor.star create mode 100644 test_suite/testdata/java/int_function.star create mode 100644 test_suite/testdata/java/list_mutation.star create mode 100644 test_suite/testdata/java/list_slices.star create mode 100644 test_suite/testdata/java/min_max.star create mode 100644 test_suite/testdata/java/range.star create mode 100644 test_suite/testdata/java/reversed.star create mode 100644 test_suite/testdata/java/string_elems.star create mode 100644 test_suite/testdata/java/string_find.star create mode 100644 test_suite/testdata/java/string_format.star create mode 100644 test_suite/testdata/java/string_misc.star create mode 100644 test_suite/testdata/java/string_partition.star create mode 100644 test_suite/testdata/java/string_slice_index.star create mode 100644 test_suite/testdata/java/string_split.star create mode 100644 test_suite/testdata/java/string_splitlines.star create mode 100644 test_suite/testdata/java/string_test_characters.star diff --git a/test_suite/BUILD b/test_suite/BUILD index 69314ce..6e1b607 100644 --- a/test_suite/BUILD +++ b/test_suite/BUILD @@ -16,7 +16,7 @@ ], main = "starlark_test.py", ) - for test_file in glob(["testdata/*"]) + for test_file in glob(["testdata/java/*"]) ] for impl, binary_rule in [("java", "@io_bazel//src/main/java/com/google/devtools/starlark:Starlark"), ("go", "@net_starlark_go//cmd/starlark:starlark"), diff --git a/test_suite/starlark_test.py b/test_suite/starlark_test.py index 324a25b..129d1eb 100644 --- a/test_suite/starlark_test.py +++ b/test_suite/starlark_test.py @@ -1,9 +1,86 @@ import sys import unittest +import tempfile +import subprocess +import os +import re import testenv class StarlarkTest(unittest.TestCase): + CHUNK_SEP = "---" + ERR_SEP = "###" + seen_error = False + + def chunks(self, path): + code = [] + expected_errors = [] + with open(path, mode="rb") as f: + for line in f: + line = line.decode("utf-8") + if line.strip() == self.CHUNK_SEP: + yield code, expected_errors + expected_errors = [] + code = [] + else: + code.append(line) + i = line.find(self.ERR_SEP) + if i >= 0: + expected_errors.append(line[i + len(self.ERR_SEP):].strip()) + yield code, expected_errors + + def evaluate(self, f): + """Execute Starlark file, return stderr.""" + proc = subprocess.Popen( + [binary_path, f], stderr=subprocess.PIPE, stdout=subprocess.PIPE) + _, stderr = proc.communicate() + return stderr + + def check_output(self, output, expected): + if expected and not output: + self.seen_error = True + print("Expected error:", expected) + + if output and not expected: + self.seen_error = True + print("Unexpected error:", output) + + output_ = output.lower() + for exp in expected: + exp = exp.lower() + # 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): + if x != y: + print("%r != %r" % (x, y)) + +def assert_ne(x, y): + if x == y: + print("%r == %r" % (x, y)) + +def assert_(cond, msg="assertion failed"): + if not cond: + print(msg) +""" + + def testFile(self): + f = test_file + print("===", f, "===") + for chunk, expected in self.chunks(f): + with tempfile.NamedTemporaryFile( + mode="wb", suffix=".star", delete=False) as tmp: + lines = [line.encode("utf-8") for line in + [self.PRELUDE] + chunk] + tmp.writelines(lines) + 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") pass if __name__ == "__main__": diff --git a/test_suite/testdata/empty.star b/test_suite/testdata/empty.star deleted file mode 100644 index e69de29..0000000 diff --git a/test_suite/testdata/java/all_any.star b/test_suite/testdata/java/all_any.star new file mode 100644 index 0000000..882e77a --- /dev/null +++ b/test_suite/testdata/java/all_any.star @@ -0,0 +1,43 @@ +# All with empty value +assert_eq(all([]), True) + +# All with list +assert_eq(all(['t', 'e']), True) +assert_eq(all([False]), False) +assert_eq(all([True, False]), False) +assert_eq(all([False, False]), False) +assert_eq(all([False, True]), False) +assert_eq(all(['', True]), False) +assert_eq(all([0, True]), False) +assert_eq(all([[], True]), False) +assert_eq(all([True, 't', 1]), True) + +# All with dict +assert_eq(all({1 : None}), True) +assert_eq(all({None : 1}), False) + +# Any with empty value +assert_eq(any([]), False) + +# Any with list +assert_eq(any([False]), False) +assert_eq(any([0]), False) +assert_eq(any(['']), False) +assert_eq(any([[]]), False) +assert_eq(any([True, False]), True) +assert_eq(any([False, False]), False) +assert_eq(any([False, '', 0]), False) +assert_eq(any([False, '', 42]), True) + +# Any with dict +assert_eq(any({1 : None, '' : None}), True) +assert_eq(any({None : 1, '' : 2}), False) + +--- +all(None) ### iterable +--- +any(None) ### iterable +--- +any(1) ### iterable +--- +all(1) ### iterable diff --git a/test_suite/testdata/java/and_or_not.star b/test_suite/testdata/java/and_or_not.star new file mode 100644 index 0000000..63e5e60 --- /dev/null +++ b/test_suite/testdata/java/and_or_not.star @@ -0,0 +1,43 @@ +assert_eq(8 or 9, 8) +assert_eq(0 or 9, 9) +assert_eq(8 and 9, 9) +assert_eq(0 and 9, 0) + +assert_eq(1 and 2 or 3, 2) +assert_eq(0 and 2 or 3, 3) +assert_eq(1 and 0 or 3, 3) + +assert_eq(1 or 2 and 3, 1) +assert_eq(0 or 2 and 3, 3) +assert_eq(0 or 0 and 3, 0) +assert_eq(1 or 0 and 3, 1) + +assert_eq(None and 1, None) +assert_eq("" or 9, 9) +assert_eq("abc" or 9, "abc") + +# check that fail() is not evaluated +assert_eq(8 or fail("do not execute"), 8) +assert_eq(0 and fail("do not execute"), 0) + +assert_eq(not 1, False) +assert_eq(not "", True) +assert_eq(not not 1, True) + +assert_eq(not 0 + 0, True) +assert_eq(not 2 - 1, False) + +assert_eq(not (0 and 0), True) +assert_eq(not (1 or 0), False) + +assert_eq(0 and not 0, 0) +assert_eq(not 0 and 0, 0) + +assert_eq(1 and not 0, True) +assert_eq(not 0 or 0, True) + +assert_eq(not 1 or 0, 0) +assert_eq(not 1 or 1, 1) + +assert_eq(not [], True) +assert_eq(not {"a": 1}, False) diff --git a/test_suite/testdata/java/dict.star b/test_suite/testdata/java/dict.star new file mode 100644 index 0000000..9d58adf --- /dev/null +++ b/test_suite/testdata/java/dict.star @@ -0,0 +1,87 @@ +# creation + +foo = {'a': 1, 'b': [1, 2]} +bar = dict(a=1, b=[1, 2]) +baz = dict({'a': 1, 'b': [1, 2]}) + +assert_eq(foo, bar) +assert_eq(foo, baz) + +# get/setdefault + +assert_eq(foo.get('a'), 1) +assert_eq(bar.get('b'), [1, 2]) +assert_eq(baz.get('c'), None) +assert_eq(baz.setdefault('c', 15), 15) +assert_eq(baz.setdefault('c'), 15) +assert_eq(baz.setdefault('c', 20), 15) +assert_eq(baz.setdefault('d'), None) + +# items + +assert_eq(foo.items(), [('a', 1), ('b', [1, 2])]) + +# keys + +assert_eq(bar.keys(), ['a', 'b']) + +# values + +assert_eq(baz.values(), [1, [1, 2], 15, None]) + +# pop/popitem + +assert_eq(baz.pop('d'), None) +assert_eq(foo.pop('a'), 1) +assert_eq(bar.popitem(), ('a', 1)) +assert_eq(foo, bar) +assert_eq(foo.pop('a', 0), 0) +assert_eq(foo.popitem(), ('b', [1, 2])) + +--- +dict().popitem() ### empty +--- +dict(a=2).pop('z') ### key +--- + +# update + +foo = dict() +baz = dict(a=1, b=[1, 2]) +bar = dict(b=[1, 2]) + +foo.update(baz) +bar.update(a=1) +baz.update({'c': 3}) +foo.update([('c', 3)]) +bar['c'] = 3 +quz = dict() +quz.update(bar.items()) + +assert_eq(foo, bar) +assert_eq(foo, baz) +assert_eq(foo, quz) +--- + +d = {"b": 0} +d.update({"a": 1}, b = 2) +d.update({"c": 0}, c = 3, d = 4) +d.update([("e", 5)]) + +# _inconsistency_: rust dict.update doesn't accept tuples +# d.update((["f", 0],), f = 6) +# expected = {"a": 1, "b": 2, "c": 3, "d": 4, "e": 5, "f": 6} + +expected = {"a": 1, "b": 2, "c": 3, "d": 4, "e": 5} +assert_eq(d, expected) + + +# creation with repeated keys + +d1 = dict([('a', 1)], a=2) +d2 = dict({'a': 1}, a=2) +d3 = dict([('a', 1), ('a', 2)]) + +assert_eq(d1['a'], 2) +assert_eq(d1, d2) +assert_eq(d1, d3) diff --git a/test_suite/testdata/java/equality.star b/test_suite/testdata/java/equality.star new file mode 100644 index 0000000..89a6009 --- /dev/null +++ b/test_suite/testdata/java/equality.star @@ -0,0 +1,69 @@ +# == operator +assert_eq(1 == 1, True) +assert_eq(1 == 2, False) +assert_eq('hello' == 'hel' + 'lo', True) +assert_eq('hello' == 'bye', False) +assert_eq(None == None, True) +assert_eq([1, 2] == [1, 2], True) +assert_eq([1, 2] == [2, 1], False) +assert_eq({'a': 1, 'b': 2} == {'b': 2, 'a': 1}, True) +assert_eq({'a': 1, 'b': 2} == {'a': 1}, False) +assert_eq({'a': 1, 'b': 2} == {'a': 1, 'b': 2, 'c': 3}, False) +assert_eq({'a': 1, 'b': 2} == {'a': 1, 'b': 3}, False) + +# != operator +assert_eq(1 != 1, False) +assert_eq(1 != 2, True) +assert_eq('hello' != 'hel' + 'lo', False) +assert_eq('hello' != 'bye', True) +assert_eq([1, 2] != [1, 2], False) +assert_eq([1, 2] != [2, 1], True) +assert_eq({'a': 1, 'b': 2} != {'b': 2, 'a': 1}, False) +assert_eq({'a': 1, 'b': 2} != {'a': 1}, True) +assert_eq({'a': 1, 'b': 2} != {'a': 1, 'b': 2, 'c': 3}, True) +assert_eq({'a': 1, 'b': 2} != {'a': 1, 'b': 3}, True); + +# equality precedence +assert_eq(1 + 3 == 2 + 2, True) +assert_eq(not 1 == 2, True) +assert_eq(not 1 != 2, False) +assert_eq(2 and 3 == 3 or 1, True) +assert_eq(2 or 3 == 3 and 1, 2); + +# < operator +assert_eq(1 <= 1, True) +assert_eq(1 < 1, False) +assert_eq('a' <= 'b', True) +assert_eq('c' < 'a', False); + +# <= and < operators +assert_eq(1 <= 1, True) +assert_eq(1 < 1, False) +assert_eq('a' <= 'b', True) +assert_eq('c' < 'a', False); + +# >= and > operators +assert_eq(1 >= 1, True) +assert_eq(1 > 1, False) +assert_eq('a' >= 'b', False) +assert_eq('c' > 'a', True); + +# list/tuple comparison +assert_eq([] < [1], True) +assert_eq([1] < [1, 1], True) +assert_eq([1, 1] < [1, 2], True) +assert_eq([1, 2] < [1, 2, 3], True) +assert_eq([1, 2, 3] <= [1, 2, 3], True) + +assert_eq(['a', 'b'] > ['a'], True) +assert_eq(['a', 'b'] >= ['a'], True) +assert_eq(['a', 'b'] < ['a'], False) +assert_eq(['a', 'b'] <= ['a'], False) + +assert_eq(('a', 'b') > ('a', 'b'), False) +assert_eq(('a', 'b') >= ('a', 'b'), True) +assert_eq(('a', 'b') < ('a', 'b'), False) +assert_eq(('a', 'b') <= ('a', 'b'), True) + +assert_eq([[1, 1]] > [[1, 1], []], False) +assert_eq([[1, 1]] < [[1, 1], []], True) diff --git a/test_suite/testdata/java/int.star b/test_suite/testdata/java/int.star new file mode 100644 index 0000000..354f05a --- /dev/null +++ b/test_suite/testdata/java/int.star @@ -0,0 +1,66 @@ +# Tests of Skylark 'int' + +# basic arithmetic +assert_eq(0 - 1, -1) +assert_eq(1 + 1, 2) +assert_eq(5 + 7, 12) +assert_eq(5 * 7, 35) +assert_eq(5 - 7, -2) + +# truth +assert_(123) +assert_(-1) +assert_(not 0) + +# comparisons +assert_(5 > 2) +assert_(2 + 1 == 3) +assert_(2 + 1 >= 3) +assert_(not (2 + 1 > 3)) +assert_(2 + 2 <= 5) +assert_(not (2 + 1 < 3)) + +# division +assert_eq(100 // 7, 14) +assert_eq(100 // -7, -15) +assert_eq(-100 // 7, -15) # NB: different from Go / Java +assert_eq(-100 // -7, 14) # NB: different from Go / Java +assert_eq(98 // 7, 14) +assert_eq(98 // -7, -14) +assert_eq(-98 // 7, -14) +assert_eq(-98 // -7, 14) + +# remainder +assert_eq(100 % 7, 2) +assert_eq(100 % -7, -5) # NB: different from Go / Java +assert_eq(-100 % 7, 5) # NB: different from Go / Java +assert_eq(-100 % -7, -2) +assert_eq(98 % 7, 0) +assert_eq(98 % -7, 0) +assert_eq(-98 % 7, 0) +assert_eq(-98 % -7, 0) + +# precedence +assert_eq(5 - 7 * 2 + 3, -6) +assert_eq(4 * 5 // 2 + 5 // 2 * 4, 18) + +# compound assignment +def compound(): + x = 1 + x += 1 + assert_eq(x, 2) + x -= 3 + assert_eq(x, -1) + x *= 10 + assert_eq(x, -10) + x //= -2 + assert_eq(x, 5) + x %= 3 + assert_eq(x, 2) + +compound() + +--- +1 // 0 ### division by zero +--- +1 % 0 ### integer modulo by zero diff --git a/test_suite/testdata/java/int_constructor.star b/test_suite/testdata/java/int_constructor.star new file mode 100644 index 0000000..6833c1c --- /dev/null +++ b/test_suite/testdata/java/int_constructor.star @@ -0,0 +1,44 @@ +assert_eq(int('1'), 1) +assert_eq(int('-1234'), -1234) +assert_eq(int(42), 42) +assert_eq(int(-1), -1) +assert_eq(int(True), 1) +assert_eq(int(False), 0) +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('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('1.5') ### invalid literal +--- +int('ab') ### invalid literal +--- +int(None) ### None +--- +int('123', 3) ### invalid literal +--- +int('FF', 15) ### invalid literal +--- +int('123', -1) ### >= 2 (and|&&) <= 36 +--- +int('123', 1) ### >= 2 (and|&&) <= 36 +--- +int('123', 37) ### >= 2 (and|&&) <= 36 +--- +int('0xFF', 8) ### invalid literal +--- +int(True, 2) ### can't convert non-string with explicit base +--- +int(1, 2) ### can't convert non-string with explicit base +--- +int(True, 10) ### can't convert non-string with explicit base diff --git a/test_suite/testdata/java/int_function.star b/test_suite/testdata/java/int_function.star new file mode 100644 index 0000000..b6cd628 --- /dev/null +++ b/test_suite/testdata/java/int_function.star @@ -0,0 +1,97 @@ +# 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 +--- +# This case is allowed in Python but not Skylark +int() ### x +--- + +# 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) + +--- +# _inconsistency_: go, rust allow 64-bit ints +# int(2147483648) ## invalid base-10 integer constant: 2147483648 +--- +# int(-2147483649) ## invalid base-10 integer constant: 2147483649 +--- +int('') ### (cannot be empty|invalid literal) +--- +# Surrounding whitespace is not allowed +int(' 42 ') ### invalid literal +--- +int('-') ### invalid literal +--- +int('0x') ### invalid literal +--- +int('1.5') ### invalid literal +--- +int('ab') ### invalid literal +--- + +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) + +--- +# _inconsistency_: rust doesn't complain about this +# invalid base +# int('016', 0) ## base.*016 +--- +int('123', 3) ### invalid literal +--- +int('FF', 15) ### invalid literal +--- +int('123', -1) ### >= 2 (and|&&) <= 36 +--- +int('123', 1) ### >= 2 (and|&&) <= 36 +--- +int('123', 37) ### >= 2 (and|&&) <= 36 +--- +int('123', 'x') ### base must be an integer +--- + +# 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 +--- +int(True, 2) ### can't convert non-string with explicit base +--- +int(1, 2) ### can't convert non-string with explicit base +--- +int(True, 10) ### can't convert non-string with explicit base diff --git a/test_suite/testdata/java/list_mutation.star b/test_suite/testdata/java/list_mutation.star new file mode 100644 index 0000000..64ae860 --- /dev/null +++ b/test_suite/testdata/java/list_mutation.star @@ -0,0 +1,90 @@ +# 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) ### no (method insert|\.insert field) +--- + +# 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) ### no (method append|\.append field) +--- + +# 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]) ### no (method extend|\.extend field) +--- +[1, 2].extend(3) ### (expected value of type|got int, want iterable) + +# 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) ### no (method remove|\.remove field) +--- +[1, 2].remove(3) ### not found +--- + +# pop + +li1 = [2, 3, 4] +assert_eq(li1.pop(), 4) +assert_eq(li1, [2, 3]) + +li2 = [2, 4] +#li2 = [2, 3, 4] +# _inconsistency_: rust pop() method doesn't support -ve indices +# 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( 3)? out of range +--- +(1, 2).pop() ### no (method pop|\.pop field) diff --git a/test_suite/testdata/java/list_slices.star b/test_suite/testdata/java/list_slices.star new file mode 100644 index 0000000..03f1de1 --- /dev/null +++ b/test_suite/testdata/java/list_slices.star @@ -0,0 +1,84 @@ +# Without step +assert_eq([0, 1, 2, 3][0:-1], [0, 1, 2]) +assert_eq([0, 1, 2, 3, 4, 5][2:4], [2, 3]) +assert_eq([0, 1, 2, 3, 4, 5][-2:-1], [4]) +assert_eq([][1:2], []) +assert_eq([0, 1, 2, 3][-10:10], [0, 1, 2, 3]) + +# With step +assert_eq([1, 2, 3, 4, 5][::1], [1, 2, 3, 4, 5]) +assert_eq([1, 2, 3, 4, 5][1::1], [2, 3, 4, 5]) +assert_eq([1, 2, 3, 4, 5][:2:1], [1, 2]) +assert_eq([1, 2, 3, 4, 5][1:3:1], [2, 3]) +assert_eq([1, 2, 3, 4, 5][-4:-2:1], [2, 3]) +assert_eq([1, 2, 3, 4, 5][-10:10:1], [1, 2, 3, 4, 5]) +assert_eq([1, 2, 3, 4, 5][::42], [1]) +assert_eq([][::1], []) +assert_eq([][::-1], []) +assert_eq([1, 2, 3, 4, 5, 6, 7][::3], [1, 4, 7]) +assert_eq([1, 2, 3, 4, 5, 6, 7, 8, 9][1:7:3], [2, 5]) +assert_eq([1, 2, 3][3:1:1], []) +assert_eq([1, 2, 3][1:3:-1], []) + +# Negative step +assert_eq([1, 2, 3, 4, 5][::-1], [5, 4, 3, 2, 1]) +assert_eq([1, 2, 3, 4, 5][4::-1], [5, 4, 3, 2, 1]) +assert_eq([1, 2, 3, 4, 5][:0:-1], [5, 4, 3, 2]) +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]) + +# None +assert_eq([1, 2, 3][None:None:None], [1, 2, 3]) +assert_eq([1, 2, 3][None:None], [1, 2, 3]) +assert_eq([1, 2, 3][None:2:None], [1, 2]) + +# Tuples +assert_eq(()[1:2], ()) +assert_eq(()[::1], ()) +assert_eq((0, 1, 2, 3)[0:-1], (0, 1, 2)) +assert_eq((0, 1, 2, 3, 4, 5)[2:4], (2, 3)) +assert_eq((0, 1, 2, 3)[-10:10], (0, 1, 2, 3)) +assert_eq((1, 2, 3, 4, 5)[-10:10:1], (1, 2, 3, 4, 5)) +assert_eq((1, 2, 3, 4, 5, 6, 7, 8, 9)[1:7:3], (2, 5)) +assert_eq((1, 2, 3, 4, 5)[::-1], (5, 4, 3, 2, 1)) +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'|invalid start index) +--- +'123'[:'b':] ### (slice end must be an integer, not 'b'|invalid end index) +--- +(1, 2, 3)[1::0] ### (slice step cannot be zero|zero is not a valid slice step) +--- +[1, 2, 3][::0] ### (slice step cannot be zero|zero is not a valid slice step) +--- +[1, 2, 3][1::0] ### (slice step cannot be zero|zero is not a valid slice step) +--- +[1, 2, 3][:3:0] ### (slice step cannot be zero|zero is not a valid slice step) +--- +[1, 2, 3][1:3:0] ### (slice step cannot be zero|zero is not a valid slice step) +--- +[[1], [2]]['a'] ### (indices must be integers, not string|got string, want int) +--- +[0, 1, 2][3] ### index( 3)? out of range +--- +[0, 1, 2][-4] ### index( -4)? out of range +--- +[0][-2] ### index( -2)? out of range +--- +[0][1] ### index( 1)? out of range +--- +[][1] ### index( 1)? out of range diff --git a/test_suite/testdata/java/min_max.star b/test_suite/testdata/java/min_max.star new file mode 100644 index 0000000..9f84490 --- /dev/null +++ b/test_suite/testdata/java/min_max.star @@ -0,0 +1,53 @@ +# min / max + +# _inconsistency_: rust elems() returns list of ints +# assert_eq(min("abcdefxyz".elems()), "a") + +assert_eq(min("test", "xyz"), "test") + +assert_eq(min([4, 5], [1]), [1]) +assert_eq(min([1, 2], [3]), [1, 2]) +assert_eq(min([1, 5], [1, 6], [2, 4], [0, 6]), [0, 6]) +assert_eq(min([-1]), -1) +assert_eq(min([5, 2, 3]), 2) +assert_eq(min({1: 2, -1 : 3}), -1) +assert_eq(min({2: None}), 2) +assert_eq(min(-1, 2), -1) +assert_eq(min(5, 2, 3), 2) +assert_eq(min(1, 1, 1, 1, 1, 1), 1) +assert_eq(min([1, 1, 1, 1, 1, 1]), 1) + +# _inconsistency_: rust elems() returns list of ints +# assert_eq(max("abcdefxyz".elems()), "z") + +assert_eq(max("test", "xyz"), "xyz") +assert_eq(max("test", "xyz"), "xyz") +assert_eq(max([1, 2], [5]), [5]) +assert_eq(max([-1]), -1) +assert_eq(max([5, 2, 3]), 5) +assert_eq(max({1: 2, -1 : 3}), 1) +assert_eq(max({2: None}), 2) +assert_eq(max(-1, 2), 2) +assert_eq(max(5, 2, 3), 5) +assert_eq(max(1, 1, 1, 1, 1, 1), 1) +assert_eq(max([1, 1, 1, 1, 1, 1]), 1) + +--- +min(1) ### not iterable +--- +min([]) ### (expected at least one item|empty sequence) +--- +max([]) ### (expected at least one item|empty sequence) +--- +max(1) ### not iterable +--- + +# _inconsistency_: rust supports comparision between ints and strings +# min(1, "2", True) ## (Cannot compare int with string|not implemented) +--- +# min([1, "2", True]) ## (Cannot compare int with string|not implemented) +--- +# max(1, '2', True) ## (Cannot compare int with string|not implemented) +--- +# max([1, '2', True]) ## (Cannot compare int with string|not implemented) +--- diff --git a/test_suite/testdata/java/range.star b/test_suite/testdata/java/range.star new file mode 100644 index 0000000..ed8ce35 --- /dev/null +++ b/test_suite/testdata/java/range.star @@ -0,0 +1,17 @@ +assert_eq(list(range(5)), [0, 1, 2, 3, 4]) +assert_eq(list(range(0)), []) +assert_eq(list(range(1)), [0]) +assert_eq(list(range(-2)), []) +assert_eq(list(range(-3, 2)), [-3, -2, -1, 0, 1]) +assert_eq(list(range(3, 2)), []) +assert_eq(list(range(3, 3)), []) +assert_eq(list(range(3, 4)), [3]) +assert_eq(list(range(3, 5)), [3, 4]) +assert_eq(list(range(-3, 5, 2)), [-3, -1, 1, 3]) +assert_eq(list(range(-3, 6, 2)), [-3, -1, 1, 3, 5]) +assert_eq(list(range(5, 0, -1)), [5, 4, 3, 2, 1]) +assert_eq(list(range(5, 0, -10)), [5]) +assert_eq(list(range(0, -3, -2)), [0, -2]) + +--- +range(2, 3, 0) ### step diff --git a/test_suite/testdata/java/reversed.star b/test_suite/testdata/java/reversed.star new file mode 100644 index 0000000..1c15a6e --- /dev/null +++ b/test_suite/testdata/java/reversed.star @@ -0,0 +1,32 @@ +# lists + +assert_eq(reversed([]), []) + +# _inconsistency_: rust returns list of ints +# assert_eq(reversed('a'.elems()), ['a']) +# assert_eq(reversed('abc'.elems()), ['c', 'b', 'a']) +# assert_eq(reversed('__test '.elems()), [' ', ' ', 't', 's', 'e', 't', '_', '_']) +# assert_eq(reversed('bbb'.elems()), ['b', 'b', 'b']) + +--- +reversed(None) ### (parameter 'sequence' cannot be None|got NoneType, want iterable) +--- +reversed(1) ### (type 'int' is not iterable|got int, want iterable) +--- +# _inconsistency_: go, rust reversed() accepts dict as argument +# 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"]) diff --git a/test_suite/testdata/java/string_elems.star b/test_suite/testdata/java/string_elems.star new file mode 100644 index 0000000..8ae0e36 --- /dev/null +++ b/test_suite/testdata/java/string_elems.star @@ -0,0 +1,15 @@ +# _inconsistency_: rust elems() returns list of ints + +# string.elems +# assert_eq(list("abcd".elems()), ["a", "b", "c", "d"]) + +# assert_eq(len("aaa".elems()), 3) + +def test_iter(): + i = 0 + for c in "abcd".elems(): + assert_eq(c, "abcd"[i]) + i += 1 + assert_eq(i, 4) + +# test_iter() diff --git a/test_suite/testdata/java/string_find.star b/test_suite/testdata/java/string_find.star new file mode 100644 index 0000000..abe8adf --- /dev/null +++ b/test_suite/testdata/java/string_find.star @@ -0,0 +1,31 @@ +assert_eq('banana'.find('na'), 2) +assert_eq('banana'.find('na', 3, 1), -1) +assert_eq('aaaa'.find('a', 1, 1), -1) +assert_eq('aaaa'.find('a', 1, 50), 1) +assert_eq('aaaa'.find('aaaaa'), -1) +assert_eq('abababa'.find('ab', 1), 2) +assert_eq('abababa'.find('ab', 0), 0) +assert_eq('abababa'.find('ab', -1), -1) +assert_eq('abababa'.find('ab', -2), -1) +assert_eq('abababa'.find('ab', -3), 4) +assert_eq('abababa'.find('ab', 0, 1), -1) +assert_eq('abababa'.find('ab', 0, 2), 0) +assert_eq('abababa'.find('ab', -1000), 0) +assert_eq('abababa'.find('ab', 1000), -1) +assert_eq(''.find('a', 1), -1) + +assert_eq('banana'.rfind('na'), 4) +assert_eq('banana'.rfind('na', 3, 1), -1) +assert_eq('aaaa'.rfind('a', 1, 1), -1) +assert_eq('aaaa'.rfind('a', 1, 50), 3) +assert_eq('aaaa'.rfind('aaaaa'), -1) +assert_eq('abababa'.rfind('ab', 1), 4) +assert_eq('abababa'.rfind('ab', 0), 4) +assert_eq('abababa'.rfind('ab', -1), -1) +assert_eq('abababa'.rfind('ab', -2), -1) +assert_eq('abababa'.rfind('ab', -3), 4) +assert_eq('abababa'.rfind('ab', 0, 1), -1) +assert_eq('abababa'.rfind('ab', 0, 2), 0) +assert_eq('abababa'.rfind('ab', -1000), 4) +assert_eq('abababa'.rfind('ab', 1000), -1) +assert_eq(''.rfind('a', 1), -1) diff --git a/test_suite/testdata/java/string_format.star b/test_suite/testdata/java/string_format.star new file mode 100644 index 0000000..927ae8d --- /dev/null +++ b/test_suite/testdata/java/string_format.star @@ -0,0 +1,94 @@ +assert_eq('abc'.format(), "abc") + +# named arguments +assert_eq('x{key}x'.format(key = 2), "x2x") +assert_eq('x{key}x'.format(key = 'abc'), "xabcx") +assert_eq('{a}{b}{a}{b}'.format(a = 3, b = True), "3True3True") +assert_eq('{a}{b}{a}{b}'.format(a = 3, b = True), "3True3True") +assert_eq('{s1}{s2}'.format(s1 = ['a'], s2 = 'a'), "[\"a\"]a") +assert_eq('{a}'.format(a = '$'), "$") +assert_eq('{a}'.format(a = '$a'), "$a") +assert_eq('{a}$'.format(a = '$a'), "$a$") +assert_eq('{(}'.format(**{'(': 2}), "2") + +# curly brace escaping +assert_eq('{{}}'.format(), "{}") +assert_eq('{{}}'.format(42), "{}") +assert_eq('{{ }}'.format(), "{ }") +assert_eq('{{ }}'.format(42), "{ }") +assert_eq('{{{{}}}}'.format(), "{{}}") +assert_eq('{{{{}}}}'.format(42), "{{}}") +assert_eq('{{0}}'.format(42), "{0}") +assert_eq('{{}}'.format(42), "{}") +assert_eq('{{{}}}'.format(42), "{42}") +assert_eq('{{ '.format(42), "{ " ) +assert_eq(' }}'.format(42), " }") +assert_eq('{{ {}'.format(42), "{ 42") +assert_eq('{} }}'.format(42), "42 }") +assert_eq('{{0}}'.format(42), "{0}") +assert_eq('{{{0}}}'.format(42), "{42}") +assert_eq('{{ 0'.format(42), "{ 0") +assert_eq('0 }}'.format(42), "0 }") +assert_eq('{{ {0}'.format(42), "{ 42") +assert_eq('{0} }}'.format(42), "42 }") +assert_eq('{{test}}'.format(test = 42), "{test}") +assert_eq('{{{test}}}'.format(test = 42), "{42}") +assert_eq('{{ test'.format(test = 42), "{ test") +assert_eq('test }}'.format(test = 42), "test }") +assert_eq('{{ {test}'.format(test = 42), "{ 42") +assert_eq('{test} }}'.format(test = 42), "42 }") + + +# Automatic positionals +assert_eq('{}, {} {} {} test'.format('hi', 'this', 'is', 'a'), "hi, this is a test") +assert_eq('skip some {}'.format('arguments', 'obsolete', 'deprecated'), "skip some arguments") + +# with numbered positions +assert_eq('{0}, {1} {2} {3} test'.format('hi', 'this', 'is', 'a'), "hi, this is a test") +assert_eq('{3}, {2} {1} {0} test'.format('a', 'is', 'this', 'hi'), "hi, this is a test") +assert_eq('skip some {0}'.format('arguments', 'obsolete', 'deprecated'), "skip some arguments") +assert_eq('{0} can be reused: {0}'.format('this', 'obsolete'), "this can be reused: this") + +# Mixed fields +assert_eq('{test} and {}'.format(2, test = 1), "1 and 2") +assert_eq('{test} and {0}'.format(2, test = 1), "1 and 2") + +--- +'{{}'.format(1) ### (Found '}' without matching '{'|single '}') +--- +'{}}'.format(1) ### (Found '}' without matching '{'|single '}') +--- +'{0}'.format() ### (No replacement found for index 0|index out of range) +--- +'{0} and {1}'.format('this') ### (No replacement found for index 1|index out of range) +--- +'{0} and {2}'.format('this', 'that') ### (No replacement found for index 2|index out of range) +--- +# _inconsistency_: -0 not allowed in go,rust, different error +# '{-0} and {-1}'.format('this', 'that') ## +--- +'{0,1} and {1}'.format('this', 'that') ### (Invalid character ',' inside replacement field|not found) +--- +'{0.1} and {1}'.format('this', 'that') ### (Invalid character '.' inside replacement field|not supported) +--- +'{}'.format() ### (No replacement found for index 0|index out of range) +--- +'{} and {}'.format('this') ### (No replacement found for index 1|index out of range) +--- +'{test} and {}'.format(test = 1, 2) ### positional argument +--- +'{test} and {0}'.format(test = 1, 2) ### positional argument +--- +'{} and {1}'.format(1, 2) ### Cannot (mix|switch) +--- +'{1} and {}'.format(1, 2) ### Cannot (mix|switch) +--- +'{test.}'.format(test = 1) ### (Invalid character '.' inside replacement field|not supported) +--- +'{test[}'.format(test = 1) ### (Invalid character '\[' inside replacement field|not supported) +--- +'{test,}'.format(test = 1) ### (Invalid character ',' inside replacement field|not found) +--- +'{ {} }'.format(42) ### Nested replacement fields +--- +'{a}{b}'.format(a = 5) ### (Missing argument 'b'|keyword b not found) diff --git a/test_suite/testdata/java/string_misc.star b/test_suite/testdata/java/string_misc.star new file mode 100644 index 0000000..e71f372 --- /dev/null +++ b/test_suite/testdata/java/string_misc.star @@ -0,0 +1,156 @@ +# join +assert_eq('-'.join(['a', 'b', 'c']), "a-b-c") + +--- +join(' ', ['a', 'b', 'c']) ### (name 'join' is not defined|undefined) +--- + +assert_eq(''.join([(x + '*') for x in ['a', 'b', 'c']]), "a*b*c*") +li = [(y + '*' + z + '|') for y in ['a', 'b', 'c'] for z in ['d', 'e']] +assert_eq(''.join(li), "a*d|a*e|b*d|b*e|c*d|c*e|") + +# lower, upper +assert_eq('Blah Blah'.lower(), "blah blah") +assert_eq('ein bier'.upper(), "EIN BIER") +assert_eq(''.upper(), "") + +# title +assert_eq('this is a very simple test'.title(), "This Is A Very Simple Test") +assert_eq('Do We Keep Capital Letters?'.title(), "Do We Keep Capital Letters?") +assert_eq("this isn't just an ol' apostrophe test".title(), + "This Isn'T Just An Ol' Apostrophe Test") +assert_eq('Let us test crazy characters: _bla.exe//foo:bla(test$class)'.title(), + "Let Us Test Crazy Characters: _Bla.Exe//Foo:Bla(Test$Class)") +assert_eq('WE HAve tO lOWERCASE soMEthING heRE, AI?'.title(), + "We Have To Lowercase Something Here, Ai?") +assert_eq('wh4t ab0ut s0me numb3rs'.title(), "Wh4T Ab0Ut S0Me Numb3Rs") + +# _inconsistency_: rust's capitalize() implementation is different from go, java +# capitalize +# assert_eq('hello world'.capitalize(), "Hello world") +# assert_eq('HELLO WORLD'.capitalize(), "Hello world") +# assert_eq('12 lower UPPER 34'.capitalize(), "12 lower upper 34") + +assert_eq(''.capitalize(), "") + + +# replace +assert_eq('banana'.replace('a', 'e'), "benene") +assert_eq('banana'.replace('a', '$()'), "b$()n$()n$()") +assert_eq('banana'.replace('a', '$'), "b$n$n$") +assert_eq('banana'.replace('a', '\\'), "b\\n\\n\\") +assert_eq('b$()n$()n$()'.replace('$()', '$($())'), "b$($())n$($())n$($())") +assert_eq('b\\n\\n\\'.replace('\\', '$()'), "b$()n$()n$()") + +assert_eq('banana'.replace('a', 'e', 2), "benena") + +# index, rindex +assert_eq('banana'.index('na'), 2) +assert_eq('abababa'.index('ab', 1), 2) +assert_eq('banana'.rindex('na'), 4) +assert_eq('abababa'.rindex('ab', 1), 4) +--- +'banana'.index('foo') ### substring (\"foo\" )?not found +--- +'banana'.rindex('foo') ### substring (\"foo\" )?not found +--- + +# endswith +assert_eq('Apricot'.endswith('cot'), True) +assert_eq('a'.endswith(''), True) +assert_eq(''.endswith(''), True) +assert_eq('Apricot'.endswith('co'), False) + +# _inconsistency_: rust endwith() accepts only a single argument +# assert_eq('Apricot'.endswith('co', -1), False) +# assert_eq('abcd'.endswith('c', -2, -1), True) +# assert_eq('abcd'.endswith('c', 1, 8), False) +# assert_eq('abcd'.endswith('d', 1, 8), True) +# assert_eq('Apricot'.endswith(('cot', 'toc')), True) +# assert_eq('Apricot'.endswith(('toc', 'cot')), True) +# assert_eq('a'.endswith(('', '')), True) +# assert_eq('a'.endswith(('', 'a')), True) +# assert_eq('a'.endswith(('a', 'a')), True) +# assert_eq(''.endswith(('a', '')), True) +# assert_eq(''.endswith(('', '')), True) +# assert_eq(''.endswith(('a', 'a')), False) +# assert_eq('a'.endswith(('a')), True) +# assert_eq('a'.endswith(('a',)), True) +# assert_eq('a'.endswith(('b',)), False) +# assert_eq('a'.endswith(()), False) +# assert_eq(''.endswith(()), False) +--- +'a'.endswith(['a']) ### (expected value of type 'string or tuple of strings'|got list) +--- +'1'.endswith((1,)) ### (got type 'int'|got int) +--- +'a'.endswith(('1', 1)) ### (got type 'int'|got int) +--- + +# startswith +assert_eq('Apricot'.startswith('Apr'), True) +assert_eq('Apricot'.startswith('A'), True) +assert_eq('Apricot'.startswith(''), True) +assert_eq('Apricot'.startswith('z'), False) +assert_eq(''.startswith(''), True) +assert_eq(''.startswith('a'), False) + +# _inconsistency_: rust startswith() accepts only a single argument +# assert_eq('Apricot'.startswith(('Apr', 'rpA')), True) +# assert_eq('Apricot'.startswith(('rpA', 'Apr')), True) +# assert_eq('a'.startswith(('', '')), True) +# assert_eq('a'.startswith(('', 'a')), True) +# assert_eq('a'.startswith(('a', 'a')), True) +# assert_eq(''.startswith(('a', '')), True) +# assert_eq(''.startswith(('', '')), True) +# assert_eq(''.startswith(('a', 'a')), False) +# assert_eq('a'.startswith(('a')), True) +# assert_eq('a'.startswith(('a',)), True) +# assert_eq('a'.startswith(('b',)), False) +# assert_eq('a'.startswith(()), False) +# assert_eq(''.startswith(()), False) +--- +'a'.startswith(['a']) ### (expected value of type 'string or tuple of strings'|got list) +--- +'1'.startswith((1,)) ### (got type 'int'|got int) +--- +'a'.startswith(('1', 1)) ### (got type 'int'|got int) +--- + +# substring +assert_eq('012345678'[0:-1], "01234567") +assert_eq('012345678'[2:4], "23") +assert_eq('012345678'[-5:-3], "45") +assert_eq('012345678'[2:2], "") +assert_eq('012345678'[2:], "2345678") +assert_eq('012345678'[:3], "012") +assert_eq('012345678'[-1:], "8") +assert_eq('012345678'[:], "012345678") +assert_eq('012345678'[-1:2], "") +assert_eq('012345678'[4:2], "") + +# count +assert_eq('abc'.count('a'), 1) +assert_eq('abc'.count('b'), 1) +assert_eq('abc'.count('c'), 1) +assert_eq('abbc'.count('b'), 2) +assert_eq('aba'.count('a'), 2) +assert_eq('aaa'.count('aa'), 1) +assert_eq('aaaa'.count('aa'), 2) +assert_eq('abc'.count('a', 0), 1) +assert_eq('abc'.count('a', 1), 0) +assert_eq('abc'.count('c', 0, 3), 1) +assert_eq('abc'.count('c', 0, 2), 0) +assert_eq('abc'.count('a', -1), 0) +assert_eq('abc'.count('c', -1), 1) +assert_eq('abc'.count('c', 0, 5), 1) +assert_eq('abc'.count('c', 0, -1), 0) +assert_eq('abc'.count('a', 0, -1), 1) + +# isalpha +assert_eq(''.isalpha(), False) +assert_eq('abz'.isalpha(), True) +assert_eq('a1'.isalpha(), False) +assert_eq('a '.isalpha(), False) +assert_eq('A'.isalpha(), True) +assert_eq('AbZ'.isalpha(), True) diff --git a/test_suite/testdata/java/string_partition.star b/test_suite/testdata/java/string_partition.star new file mode 100644 index 0000000..b89baaa --- /dev/null +++ b/test_suite/testdata/java/string_partition.star @@ -0,0 +1,41 @@ +assert_eq('lawl'.partition('a'), ('l', 'a', 'wl')) +assert_eq('lawl'.rpartition('a'), ('l', 'a', 'wl')) +assert_eq('google'.partition('o'), ('g', 'o', 'ogle')) +assert_eq('google'.rpartition('o'), ('go', 'o', 'gle')) +assert_eq('xxx'.partition('x'), ('', 'x', 'xx')) +assert_eq('xxx'.rpartition('x'), ('xx', 'x', '')) +assert_eq(''.partition('a'), ('', '', '')) +assert_eq(''.rpartition('a'), ('', '', '')) + +# _inconsistency_: go has no default value for separator in partion() +# default separator +# assert_eq('hi this is a test'.partition(), ('hi', ' ', 'this is a test')) +# assert_eq('hi this is a test'.rpartition(), ('hi this is a', ' ', 'test')) +# assert_eq('google'.partition(), ('google', '', '')) +# assert_eq('google'.rpartition(), ('', '', 'google')) + +# no match +assert_eq('google'.partition('x'), ('google', '', '')) +assert_eq('google'.rpartition('x'), ('', '', 'google')) + +# at word boundaries +assert_eq('goog'.partition('g'), ('', 'g', 'oog')) +assert_eq('goog'.rpartition('g'), ('goo', 'g', '')) +assert_eq('plex'.partition('p'), ('', 'p', 'lex')) +assert_eq('plex'.rpartition('p'), ('', 'p', 'lex')) +assert_eq('plex'.partition('x'), ('ple', 'x', '')) +assert_eq('plex'.rpartition('x'), ('ple', 'x', '')) + +assert_eq('google'.partition('oog'), ('g', 'oog', 'le')) +assert_eq('google'.rpartition('oog'), ('g', 'oog', 'le')) +assert_eq('lolgooglolgooglolgooglol'.partition('goog'), ('lol', 'goog', 'lolgooglolgooglol')) +assert_eq('lolgooglolgooglolgooglol'.rpartition('goog'), ('lolgooglolgooglol', 'goog', 'lol')) + +# full string +assert_eq('google'.partition('google'), ('', 'google', '')) +assert_eq('google'.rpartition('google'), ('', 'google', '')) + +--- +'google'.partition('') ### Empty separator +--- +'google'.rpartition('') ### Empty separator diff --git a/test_suite/testdata/java/string_slice_index.star b/test_suite/testdata/java/string_slice_index.star new file mode 100644 index 0000000..ba24986 --- /dev/null +++ b/test_suite/testdata/java/string_slice_index.star @@ -0,0 +1,60 @@ +# indexing +assert_eq('somestring'[0], "s") +assert_eq('somestring'[1], "o") +assert_eq('somestring'[4], "s") +assert_eq('somestring'[9], "g") +assert_eq('somestring'[-1], "g") +assert_eq('somestring'[-2], "n") +assert_eq('somestring'[-10], "s") + +--- +'abcdef'[10] ### out of range +--- +'abcdef'[-11] ### out of range +--- + +# slicing +assert_eq('0123'[0:-1], "012") +assert_eq('012345'[2:4], "23") +assert_eq('012345'[-2:-1], "4") +assert_eq(''[1:2], "") +assert_eq('012'[1:0], "") +assert_eq('0123'[-10:10], "0123") + +assert_eq('01234'[::1], "01234") +assert_eq('01234'[1::1], "1234") +assert_eq('01234'[:2:1], "01") +assert_eq('01234'[1:3:1], "12") +assert_eq('01234'[-4:-2:1], "12") +assert_eq('01234'[-10:10:1], "01234") +assert_eq('01234'[::42], "0") + +assert_eq(''[::1], "") +assert_eq(''[::-1], "") + +assert_eq('0123456'[::3], "036") +assert_eq('01234567'[1:7:3], "14") + +assert_eq('01234'[::-1], "43210") +assert_eq('01234'[4::-1], "43210") +assert_eq('01234'[:0:-1], "4321") +assert_eq('01234'[3:1:-1], "32") +assert_eq('01234'[::-2], "420") +assert_eq('01234'[::-10], "4") + +assert_eq('123'[3:1:1], "") +assert_eq('123'[1:3:-1], "") + +--- +'123'[::0] ### (slice step cannot be zero|not a valid slice step) +--- +'123'[1::0] ### (slice step cannot be zero|not a valid slice step) +--- +'123'[:3:0] ### (slice step cannot be zero|not a valid slice step) +--- +'123'[1:3:0] ### (slice step cannot be zero|not a valid slice step) +--- +'123'['a'::] ### (slice start must be an integer, not 'a'|want int) +--- +'123'[:'b':] ### (slice end must be an integer, not 'b'|want int) +--- diff --git a/test_suite/testdata/java/string_split.star b/test_suite/testdata/java/string_split.star new file mode 100644 index 0000000..5b95db1 --- /dev/null +++ b/test_suite/testdata/java/string_split.star @@ -0,0 +1,45 @@ +# split +assert_eq('h i'.split(' '), ['h', 'i']) +assert_eq('h i p'.split(' '), ['h', 'i', 'p']) +assert_eq('a,e,i,o,u'.split(',', 2), ['a', 'e', 'i,o,u']) +assert_eq(' 1 2 3 '.split(' '), ['', '', '1', '', '2', '', '3', '', '']) + +# rsplit +assert_eq('abcdabef'.rsplit('ab'), ['', 'cd', 'ef']) +assert_eq('google_or_gogol'.rsplit('go'), ['', 'ogle_or_', '', 'l']) + +# rsplit regex +assert_eq('foo/bar.lisp'.rsplit('.'), ['foo/bar', 'lisp']) +assert_eq('foo/bar.?lisp'.rsplit('.?'), ['foo/bar', 'lisp']) +assert_eq('fwe$foo'.rsplit('$'), ['fwe', 'foo']) +assert_eq('windows'.rsplit('*'), ['windows']) + +# rsplit no match +assert_eq(''.rsplit('o'), ['']) +assert_eq('google'.rsplit('x'), ['google']) + +# rsplit separator +assert_eq('xxxxxx'.rsplit('x'), ['', '', '', '', '', '', '']) +assert_eq('xxxxxx'.rsplit('x', 1), ['xxxxx', '']) +assert_eq('xxxxxx'.rsplit('x', 2), ['xxxx', '', '']) +assert_eq('xxxxxx'.rsplit('x', 3), ['xxx', '', '', '']) +assert_eq('xxxxxx'.rsplit('x', 4), ['xx', '', '', '', '']) +assert_eq('xxxxxx'.rsplit('x', 5), ['x', '', '', '', '', '']) +assert_eq('xxxxxx'.rsplit('x', 6), ['', '', '', '', '', '', '']) +assert_eq('xxxxxx'.rsplit('x', 7), ['', '', '', '', '', '', '']) + +# split max split +assert_eq('google'.rsplit('o'), ['g', '', 'gle']) +assert_eq('google'.rsplit('o'), ['g', '', 'gle']) +assert_eq('google'.rsplit('o', 1), ['go', 'gle']) +assert_eq('google'.rsplit('o', 2), ['g', '', 'gle']) +assert_eq('google'.rsplit('o', 3), ['g', '', 'gle']) +assert_eq('ogooglo'.rsplit('o'), ['', 'g', '', 'gl', '']) +assert_eq('ogooglo'.rsplit('o', 1), ['ogoogl', '']) +assert_eq('ogooglo'.rsplit('o', 2), ['ogo', 'gl', '']) +assert_eq('ogooglo'.rsplit('o', 3), ['og', '', 'gl', '']) +assert_eq('ogooglo'.rsplit('o', 4), ['', 'g', '', 'gl', '']) +assert_eq('ogooglo'.rsplit('o', 5), ['', 'g', '', 'gl', '']) +assert_eq('google'.rsplit('google'), ['', '']) +assert_eq('google'.rsplit('google', 1), ['', '']) +assert_eq('google'.rsplit('google', 2), ['', '']) diff --git a/test_suite/testdata/java/string_splitlines.star b/test_suite/testdata/java/string_splitlines.star new file mode 100644 index 0000000..0902b42 --- /dev/null +++ b/test_suite/testdata/java/string_splitlines.star @@ -0,0 +1,33 @@ +# Empty line +assert_eq(''.splitlines(), []) +assert_eq('\n'.splitlines(), ['']) + +# Starts with line break +assert_eq('\ntest'.splitlines(), ['', 'test']) + +# Ends with line break +assert_eq('test\n'.splitlines(), ['test']) + +# Different line breaks +assert_eq('this\nis\na\ntest'.splitlines(), ['this', 'is', 'a', 'test']) + +# _inconsistency_: go splits on \n only +# Only line breaks +# assert_eq('\r\r\r'.splitlines(), ['', '', '']) +# assert_eq('\n\r\n\r'.splitlines(), ['', '', '']) +# assert_eq('\r\n\r\n\r\n'.splitlines(), ['', '', '']) +assert_eq('\n\n\n'.splitlines(), ['', '', '']) + +# Escaped sequences +assert_eq('\n\\n\\\n'.splitlines(), ['', '\\n\\']) + +# KeepEnds +assert_eq(''.splitlines(True), []) +assert_eq('\n'.splitlines(True), ['\n']) +assert_eq('this\nis\na\ntest'.splitlines(True), ['this\n', 'is\n', 'a\n', 'test']) +assert_eq('\ntest'.splitlines(True), ['\n', 'test']) +assert_eq('test\n'.splitlines(True), ['test\n']) +assert_eq('\n\\n\\\n'.splitlines(True), ['\n', '\\n\\\n']) + +# _inconsistency_: go splits on \n only +# assert_eq('this\nis\r\na\rtest'.splitlines(True), ['this\n', 'is\r\n', 'a\r', 'test']) diff --git a/test_suite/testdata/java/string_test_characters.star b/test_suite/testdata/java/string_test_characters.star new file mode 100644 index 0000000..df81d37 --- /dev/null +++ b/test_suite/testdata/java/string_test_characters.star @@ -0,0 +1,54 @@ +# isalnum +assert_eq(''.isalnum(), False) +assert_eq('a0 33'.isalnum(), False) +assert_eq('1'.isalnum(), True) +assert_eq('a033'.isalnum(), True) + +# isdigit +assert_eq(''.isdigit(), False) +assert_eq(' '.isdigit(), False) +assert_eq('a'.isdigit(), False) +assert_eq('0234325.33'.isdigit(), False) +assert_eq('1'.isdigit(), True) +assert_eq('033'.isdigit(), True) + +# isspace +assert_eq(''.isspace(), False) +assert_eq('a'.isspace(), False) +assert_eq('1'.isspace(), False) +assert_eq('\ta\n'.isspace(), False) +assert_eq(' '.isspace(), True) +assert_eq('\t\n'.isspace(), True) + +# islower +assert_eq(''.islower(), False) +assert_eq(' '.islower(), False) +assert_eq('1'.islower(), False) +assert_eq('Almost'.islower(), False) +assert_eq('abc'.islower(), True) +assert_eq(' \nabc'.islower(), True) +assert_eq('abc def\n'.islower(), True) +assert_eq('\ta\n'.islower(), True) + +# isupper +assert_eq(''.isupper(), False) +assert_eq(' '.isupper(), False) +assert_eq('1'.isupper(), False) +assert_eq('aLMOST'.isupper(), False) +assert_eq('ABC'.isupper(), True) +assert_eq(' \nABC'.isupper(), True) +assert_eq('ABC DEF\n'.isupper(), True) +assert_eq('\tA\n'.isupper(), True) + +# istitle +assert_eq(''.istitle(), False) +assert_eq(' '.istitle(), False) +assert_eq('134'.istitle(), False) +assert_eq('almost Correct'.istitle(), False) +assert_eq('1nope Nope Nope'.istitle(), False) +assert_eq('NO Way'.istitle(), False) +assert_eq('T'.istitle(), True) +assert_eq('Correct'.istitle(), True) +assert_eq('Very Correct! Yes\nIndeed1X'.istitle(), True) +assert_eq('1234Ab Ab'.istitle(), True) +assert_eq('\tA\n'.istitle(), True)