Commit a63b495a authored by Roman Alifanov's avatar Roman Alifanov

Split test_integration.py into 8 focused test files

Fix spaces before parentheses in CT source code within tests.
parent 995944ab
......@@ -477,9 +477,17 @@ lib/ # ContenT libraries
└── cli.ct # CLI library (urfave/cli style)
tests/ # Test suite
├── helpers.py # Shared test helpers (run_ct, compile_ct)
├── test_lexer.py # Lexer tests
├── test_parser.py # Parser tests
└── test_integration.py # Integration tests
├── test_basics.py # Basic tests (print, variables, arithmetic, loops)
├── test_functions.py # Functions, lambdas, callbacks, parameter passing
├── test_classes.py # Classes, objects, field assignment
├── test_methods.py # String/array/dict methods, method validation
├── test_stdlib.py # Standard library (env, json, fs, with)
├── test_decorators.py # Decorators, typing, @test, user decorators
├── test_awk.py # AWK functions (map/filter, sync, assert)
└── test_shell.py # Shell commands, pipes, mixed pipes
examples/ # Example .ct programs
```
......
......@@ -468,10 +468,18 @@ bootstrap/ # Bootstrap-компилятор (Python)
lib/ # Библиотеки на ContenT
└── cli.ct # CLI-библиотека (стиль urfave/cli)
tests/ # Тестовый набор
├── test_lexer.py # Тесты лексера
├── test_parser.py # Тесты парсера
└── test_integration.py # Интеграционные тесты
tests/ # Тестовый набор
├── helpers.py # Общие функции тестов (run_ct, compile_ct)
├── test_lexer.py # Тесты лексера
├── test_parser.py # Тесты парсера
├── test_basics.py # Базовые тесты (print, переменные, арифметика)
├── test_functions.py # Функции, лямбды, колбеки
├── test_classes.py # Классы, объекты, присваивание полей
├── test_methods.py # Методы строк/массивов/словарей
├── test_stdlib.py # Стандартная библиотека (env, json, fs, with)
├── test_decorators.py # Декораторы, типизация, @test
├── test_awk.py # AWK-функции
└── test_shell.py # Shell-команды, pipe
examples/ # Примеры .ct программ
```
......
......@@ -2,6 +2,7 @@ import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))
sys.path.insert(0, str(Path(__file__).parent))
import pytest
from bootstrap.lexer import Lexer
......
import subprocess
import tempfile
import os
def run_ct(source: str) -> tuple[int, str, str]:
with tempfile.NamedTemporaryFile(mode='w', suffix='.ct', delete=False) as f:
f.write(source)
f.flush()
ct_file = f.name
try:
result = subprocess.run(
['python3', 'content', 'run', ct_file],
capture_output=True,
text=True,
timeout=10
)
return result.returncode, result.stdout, result.stderr
finally:
os.unlink(ct_file)
def compile_ct(source: str) -> tuple[int, str, str]:
with tempfile.NamedTemporaryFile(mode='w', suffix='.ct', delete=False) as f:
f.write(source)
f.flush()
ct_file = f.name
sh_file = ct_file.replace('.ct', '.sh')
try:
result = subprocess.run(
['python3', 'content', 'build', ct_file, '-o', sh_file],
capture_output=True,
text=True,
timeout=10
)
compiled_output = ""
if os.path.exists(sh_file):
with open(sh_file, 'r') as sf:
compiled_output = sf.read()
os.unlink(sh_file)
return result.returncode, compiled_output, result.stderr
finally:
os.unlink(ct_file)
def compile_ct_with_flags(source: str, flags: list = None) -> tuple[int, str, str]:
with tempfile.NamedTemporaryFile(mode='w', suffix='.ct', delete=False) as f:
f.write(source)
f.flush()
ct_file = f.name
sh_file = ct_file.replace('.ct', '.sh')
cmd = ['python3', 'content', 'build', ct_file, '-o', sh_file]
if flags:
cmd.extend(flags)
try:
result = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=10
)
if os.path.exists(sh_file):
os.unlink(sh_file)
return result.returncode, result.stdout, result.stderr
finally:
os.unlink(ct_file)
def compile_ct_check(source: str) -> tuple[int, str, str]:
with tempfile.NamedTemporaryFile(mode='w', suffix='.ct', delete=False) as f:
f.write(source)
f.flush()
ct_file = f.name
sh_file = ct_file.replace('.ct', '.sh')
try:
result = subprocess.run(
['python3', 'content', 'build', ct_file, '-o', sh_file],
capture_output=True,
text=True,
timeout=10
)
if os.path.exists(sh_file):
os.unlink(sh_file)
return result.returncode, result.stdout, result.stderr
finally:
os.unlink(ct_file)
def run_ct_test(source: str) -> tuple[int, str, str]:
with tempfile.NamedTemporaryFile(mode='w', suffix='.ct', delete=False) as f:
f.write(source)
f.flush()
ct_file = f.name
try:
result = subprocess.run(
['python3', 'content', 'test', ct_file],
capture_output=True,
text=True,
timeout=10
)
return result.returncode, result.stdout, result.stderr
finally:
os.unlink(ct_file)
from helpers import run_ct
class TestAwkMapFilter:
def test_awk_map(self):
code, stdout, _ = run_ct('''
@awk
func testMap (text) {
arr = []
n = text.split (" ")
for i in range (1, n + 1) {
arr.push (__split_arr[i])
}
result = arr.map (x => x * 2)
out = ""
__ct_len = length (result)
for i in range (1, __ct_len + 1) {
if (out != "") {
out = out .. " "
}
out = out .. result[i]
}
return out
}
print (testMap ("1 2 3"))
''')
assert code == 0
assert "2 4 6" in stdout
def test_awk_filter(self):
code, stdout, _ = run_ct('''
@awk
func testFilter (text) {
arr = []
n = text.split (" ")
for i in range (1, n + 1) {
arr.push (__split_arr[i])
}
result = arr.filter (x => x > 2)
out = ""
__ct_len = length (result)
for i in range (1, __ct_len + 1) {
if (out != "") {
out = out .. " "
}
out = out .. result[i]
}
return out
}
print (testFilter ("1 2 3 4 5"))
''')
assert code == 0
assert "3 4 5" in stdout
def test_awk_validate(self):
code, stdout, stderr = run_ct('''
@validate (x: "int > 0")
@awk
func double (x) {
return x * 2
}
print (double (5))
''')
assert code == 0
assert "10" in stdout
def test_awk_validate_fails(self):
code, stdout, stderr = run_ct('''
@validate (x: "int > 0")
@awk
func double (x) {
return x * 2
}
print (double (-1))
''')
assert code != 0 or "must be" in stderr
class TestAwkSync:
def test_awk_string_interpolation(self):
code, stdout, stderr = run_ct('''
@awk
func greet (name) {
return "Hello, {name}!"
}
print (greet ("World"))
''')
assert code == 0
assert "Hello, World!" in stdout
def test_awk_env_var(self):
code, stdout, stderr = run_ct('''
@awk
func get_home () {
return env.HOME
}
result = get_home ()
print (result)
''')
assert code == 0
assert "/" in stdout
def test_awk_time_now(self):
code, stdout, stderr = run_ct('''
@awk
func get_time () {
return time.now ()
}
ts = get_time ()
print (ts)
''')
assert code == 0
assert len(stdout.strip()) >= 10
def test_awk_assert_eq(self):
code, stdout, stderr = run_ct('''
@awk
func test_eq () {
x = 10
assert_eq (10, x, "should be 10")
return "passed"
}
print (test_eq ())
''')
assert code == 0
assert "passed" in stdout
def test_awk_assert_eq_fails(self):
code, stdout, stderr = run_ct('''
@awk
func test_eq () {
x = 5
assert_eq (10, x, "not equal")
return "passed"
}
test_eq ()
''')
assert code != 0
assert "not equal" in stdout or "not equal" in stderr
def test_awk_array_push_statement(self):
code, stdout, stderr = run_ct('''
@awk
func test_push () {
arr = []
arr.push (1)
arr.push (2)
arr.push (3)
return arr[1] .. "-" .. arr[2] .. "-" .. arr[3]
}
print (test_push ())
''')
assert code == 0
assert "1-2-3" in stdout
def test_awk_dict_set_statement(self):
code, stdout, stderr = run_ct('''
@awk
func test_dict () {
d = {}
d.set ("key", "value")
return d.get ("key")
}
print (test_dict ())
''')
assert code == 0
assert "value" in stdout
def test_awk_print_statement(self):
code, stdout, stderr = run_ct('''
@awk
func test_print () {
print ("inside awk")
return "done"
}
result = test_print ()
print (result)
''')
assert code == 0
assert "inside awk" in stdout
assert "done" in stdout
from helpers import run_ct, compile_ct
class TestPrint:
def test_print_string(self):
code, stdout, _ = run_ct('print ("hello")')
assert code == 0
assert "hello" in stdout
def test_print_number(self):
code, stdout, _ = run_ct('print (42)')
assert code == 0
assert "42" in stdout
def test_print_interpolation(self):
code, stdout, _ = run_ct('name = "World"\nprint ("Hello, {name}!")')
assert code == 0
assert "Hello, World!" in stdout
class TestVariables:
def test_variable_assignment(self):
code, stdout, _ = run_ct('x = 10\nprint (x)')
assert code == 0
assert "10" in stdout
def test_variable_reassignment(self):
code, stdout, _ = run_ct('x = 10\nx = 20\nprint (x)')
assert code == 0
assert "20" in stdout
class TestArithmetic:
def test_addition(self):
code, stdout, _ = run_ct('print (1 + 2)')
assert code == 0
assert "3" in stdout
def test_subtraction(self):
code, stdout, _ = run_ct('print (10 - 3)')
assert code == 0
assert "7" in stdout
def test_multiplication(self):
code, stdout, _ = run_ct('print (4 * 5)')
assert code == 0
assert "20" in stdout
def test_division(self):
code, stdout, _ = run_ct('print (10 / 2)')
assert code == 0
assert "5" in stdout
def test_modulo(self):
code, stdout, _ = run_ct('print (10 % 3)')
assert code == 0
assert "1" in stdout
class TestCompoundAssignment:
def test_plus_assign_simple(self):
code, stdout, _ = run_ct('''
x = 5
x += 3
print (x)
''')
assert code == 0
assert "8" in stdout
def test_plus_assign_with_method_call(self):
code, stdout, _ = run_ct('''
total = 0
word = "hello"
total += word.len ()
print (total)
''')
assert code == 0
assert "5" in stdout
def test_plus_assign_in_loop(self):
code, stdout, _ = run_ct('''
total = 0
foreach word in "ab cde f".split (" ") {
total += word.len ()
}
print (total)
''')
assert code == 0
assert "6" in stdout
def test_minus_assign_with_method(self):
code, stdout, _ = run_ct('''
x = 10
s = "abc"
x -= s.len ()
print (x)
''')
assert code == 0
assert "7" in stdout
class TestControlFlow:
def test_if_true(self):
code, stdout, _ = run_ct('''
x = 10
if x > 5 {
print ("big")
}
''')
assert code == 0
assert "big" in stdout
def test_if_false(self):
code, stdout, _ = run_ct('''
x = 3
if x > 5 {
print ("big")
} else {
print ("small")
}
''')
assert code == 0
assert "small" in stdout
def test_while_loop(self):
code, stdout, _ = run_ct('''
i = 0
while i < 3 {
print (i)
i += 1
}
''')
assert code == 0
assert "0" in stdout
assert "1" in stdout
assert "2" in stdout
def test_foreach_range(self):
code, stdout, _ = run_ct('''
foreach i in range (3) {
print (i)
}
''')
assert code == 0
assert "0" in stdout
assert "1" in stdout
assert "2" in stdout
class TestCompileOnly:
def test_compile_hello(self):
code, stdout, stderr = compile_ct('print ("hello")')
assert code == 0
assert "#!/usr/bin/env bash" in stdout
def test_compile_function(self):
code, stdout, stderr = compile_ct('''
func greet () {
print ("hi")
}
greet ()
''')
assert code == 0
assert "greet" in stdout
from helpers import run_ct
class TestClasses:
def test_class_instantiation(self):
code, stdout, _ = run_ct('''
class Counter {
value = 0
func inc () {
this.value += 1
}
func get () {
return this.value
}
}
c = Counter ()
c.inc ()
c.inc ()
print (c.get ())
''')
assert code == 0
assert "2" in stdout
def test_class_constructor(self):
code, stdout, _ = run_ct('''
class Person {
name = ""
construct (name) {
this.name = name
}
func greet () {
print ("Hello, {this.name}")
}
}
p = Person ("Alice")
p.greet ()
''')
assert code == 0
assert "Hello, Alice" in stdout
class TestClassInstancePassing:
def test_class_to_function_basic(self):
code, stdout, _ = run_ct('''
class Counter {
count = 0
construct (initial) {
this.count = initial
}
func increment () {
this.count += 1
}
func get () {
return this.count
}
}
func add_ten (c) {
for i in range (10) {
c.increment ()
}
}
counter = new Counter (5)
add_ten (counter)
print ("Result: {counter.get ()}")
''')
assert code == 0
assert "Result: 15" in stdout
def test_class_to_function_nested(self):
code, stdout, _ = run_ct('''
class Counter {
count = 0
construct (initial) {
this.count = initial
}
func increment () {
this.count += 1
}
func get () {
return this.count
}
}
func inner (c) {
c.increment ()
return c.get ()
}
func outer (c) {
c.increment ()
return inner (c)
}
counter = new Counter (0)
result = outer (counter)
print ("Result: {result}")
''')
assert code == 0
assert "Result: 2" in stdout
def test_class_to_method(self):
code, stdout, _ = run_ct('''
class Counter {
count = 0
construct (initial) {
this.count = initial
}
func get () {
return this.count
}
func add (amount) {
this.count += amount
}
}
class Calculator {
func double_counter (c) {
val = c.get ()
c.add (val)
}
}
counter = new Counter (5)
calc = new Calculator ()
calc.double_counter (counter)
print ("Result: {counter.get ()}")
''')
assert code == 0
assert "Result: 10" in stdout
def test_multiple_class_params_to_method(self):
code, stdout, _ = run_ct('''
class Counter {
count = 0
construct (initial) {
this.count = initial
}
func get () {
return this.count
}
func add (amount) {
this.count += amount
}
}
class Calculator {
func process (c1, c2) {
v1 = c1.get ()
v2 = c2.get ()
c1.add (v2)
c2.add (v1)
}
}
a = new Counter (5)
b = new Counter (10)
calc = new Calculator ()
calc.process (a, b)
print ("a={a.get ()}, b={b.get ()}")
''')
assert code == 0
assert "a=15, b=15" in stdout
class TestObjectFieldAssignment:
def test_simple_field_assignment(self):
code, stdout, stderr = run_ct('''
class User {
name = "default"
age = 0
}
user = new User ()
user.name = "Alice"
user.age = 25
print ("{user.name} is {user.age}")
''')
assert code == 0
assert "Alice is 25" in stdout
def test_compound_assignment_plus(self):
code, stdout, stderr = run_ct('''
class Counter {
value = 10
}
c = new Counter ()
c.value += 5
print (c.value)
''')
assert code == 0
assert "15" in stdout
def test_compound_assignment_minus(self):
code, stdout, stderr = run_ct('''
class Counter {
value = 20
}
c = new Counter ()
c.value -= 7
print (c.value)
''')
assert code == 0
assert "13" in stdout
def test_compound_assignment_multiply(self):
code, stdout, stderr = run_ct('''
class Counter {
value = 5
}
c = new Counter ()
c.value *= 3
print (c.value)
''')
assert code == 0
assert "15" in stdout
def test_compound_assignment_divide(self):
code, stdout, stderr = run_ct('''
class Counter {
value = 20
}
c = new Counter ()
c.value /= 4
print (c.value)
''')
assert code == 0
assert "5" in stdout
def test_multiple_objects_independent(self):
code, stdout, stderr = run_ct('''
class Point {
x = 0
y = 0
}
p1 = new Point ()
p2 = new Point ()
p1.x = 10
p1.y = 20
p2.x = 100
p2.y = 200
print ("{p1.x},{p1.y} {p2.x},{p2.y}")
''')
assert code == 0
assert "10,20 100,200" in stdout
def test_field_assignment_in_function(self):
code, stdout, stderr = run_ct('''
class Box {
value = 0
}
func setBox (b: Box, v) {
b.value = v
}
box = new Box ()
setBox (box, 42)
print (box.value)
''')
assert code == 0
assert "42" in stdout
def test_chained_assignments(self):
code, stdout, stderr = run_ct('''
class Counter {
value = 0
}
c = new Counter ()
c.value = 10
c.value += 5
c.value *= 2
c.value -= 10
print (c.value)
''')
assert code == 0
assert "20" in stdout
class TestDictFieldAssignment:
def test_dict_field_assign_simple(self):
code, stdout, stderr = run_ct('''
func test () {
obj = {}
obj.name = "Alice"
return obj.name
}
print (test ())
''')
assert code == 0
assert "Alice" in stdout
def test_dict_field_assign_multiple(self):
code, stdout, stderr = run_ct('''
func test () {
obj = {}
obj.name = "Bob"
obj.age = 30
return obj.name .. " is " .. obj.age
}
print (test ())
''')
assert code == 0
assert "Bob is 30" in stdout
def test_dict_field_assign_compound(self):
code, stdout, stderr = run_ct('''
func test () {
obj = {}
obj.count = 10
obj.count += 5
return obj.count
}
print (test ())
''')
assert code == 0
assert "15" in stdout
from helpers import run_ct, compile_ct, compile_ct_with_flags, run_ct_test
class TestDecorators:
def test_log_decorator(self):
code, stdout, stderr = run_ct('''
@log
func hello () {
print ("hello")
}
hello ()
''')
assert code == 0
assert "hello" in stdout
def test_retry_decorator(self):
code, stdout, _ = run_ct('''
attempt = 0
@retry (attempts=3)
func flaky () {
attempt += 1
if attempt < 3 {
throw "fail"
}
print ("success")
}
try {
flaky ()
} except {
print ("all failed")
}
''')
assert code == 0
class TestValidateDecorator:
def test_validate_int_positive(self):
code, stdout, stderr = run_ct('''
@validate (x: "int > 0")
func process (x) {
print ("ok: {x}")
}
process (5)
''')
assert code == 0
assert "ok: 5" in stdout
def test_validate_int_positive_fails(self):
code, stdout, stderr = run_ct('''
@validate (x: "int > 0")
func process (x) {
print ("ok: {x}")
}
process (-1)
''')
assert code != 0 or "Validation error" in stderr
def test_validate_int_not_integer(self):
code, stdout, stderr = run_ct('''
@validate (x: "int")
func process (x) {
print ("ok: {x}")
}
process ("hello")
''')
assert code != 0 or "must be integer" in stderr
def test_validate_multiple_params(self):
code, stdout, _ = run_ct('''
@validate (x: "int > 0", y: "int >= 0")
func add (x, y) {
print (x + y)
}
add (5, 10)
''')
assert code == 0
assert "15" in stdout
class TestTestDecorator:
def test_passing_test(self):
code, stdout, stderr = run_ct_test('''
@test ("simple test passes")
func test_simple () {
x = 5
assert (x == 5, "x should be 5")
}
''')
assert code == 0
assert "PASS" in stdout
assert "simple test passes" in stdout
def test_failing_test(self):
code, stdout, stderr = run_ct_test('''
@test ("simple test fails")
func test_simple () {
x = 5
assert (x == 10, "x should be 10")
}
''')
assert code == 1
assert "FAIL" in stdout
assert "x should be 10" in stdout
def test_multiple_tests(self):
code, stdout, stderr = run_ct_test('''
@test ("first test")
func test_one () {
assert (1 == 1, "math works")
}
@test ("second test")
func test_two () {
assert (2 == 2, "math still works")
}
''')
assert code == 0
assert "2 tests passed" in stdout
def test_with_regular_functions(self):
code, stdout, stderr = run_ct_test('''
func add (a, b) {
return a + b
}
@test ("add function works")
func test_add () {
result = add (2, 3)
assert (result == 5, "2 + 3 should be 5")
}
''')
assert code == 0
assert "PASS" in stdout
def test_awk_assert(self):
code, stdout, stderr = run_ct_test('''
@test ("awk assert works")
@awk
func test_awk () {
x = 5
assert (x == 5, "x should be 5")
}
''')
assert code == 0
assert "PASS" in stdout
def test_awk_assert_fails(self):
code, stdout, stderr = run_ct_test('''
@test ("awk assert fails")
@awk
func test_awk () {
x = 5
assert (x == 10, "x should be 10")
}
''')
assert code == 1
assert "FAIL" in stdout
def test_dce_skips_test_in_normal_mode(self):
code, stdout, stderr = compile_ct('''
@test ("this should be skipped")
func test_skipped () {
assert (1 == 1, "ok")
}
print ("hello")
''')
assert code == 0
assert "DCE: skipped @test" in stdout
assert "test_skipped" not in stdout or "skipped" in stdout
class TestUserDecorators:
def test_user_decorator_registers_handler(self):
code, stdout, _ = run_ct('''
class Router {
handlers = {}
func route (path, handler) {
this.handlers.set (path, handler)
}
func dispatch (path) {
if this.handlers.has (path) {
handler = this.handlers.get (path)
handler ()
}
}
}
router = new Router ()
@router.route ("/home")
func home_handler () {
print ("Home page")
}
router.dispatch ("/home")
''')
assert code == 0
assert "Home page" in stdout
def test_user_decorator_with_callback_args(self):
code, stdout, _ = run_ct('''
class EventBus {
listeners = {}
func on (event, handler) {
this.listeners.set (event, handler)
}
func emit (event, data) {
if this.listeners.has (event) {
handler = this.listeners.get (event)
handler (data)
}
}
}
bus = new EventBus ()
@bus.on ("click")
func on_click (data) {
print ("Clicked: {data}")
}
bus.emit ("click", "button1")
''')
assert code == 0
assert "Clicked: button1" in stdout
def test_multiple_user_decorators(self):
code, stdout, _ = run_ct('''
class Commands {
cmds = {}
func register (name, handler) {
this.cmds.set (name, handler)
}
func run (name) {
if this.cmds.has (name) {
handler = this.cmds.get (name)
handler ()
}
}
}
cmds = new Commands ()
@cmds.register ("hello")
func say_hello () {
print ("Hello!")
}
@cmds.register ("bye")
func say_bye () {
print ("Goodbye!")
}
cmds.run ("hello")
cmds.run ("bye")
''')
assert code == 0
assert "Hello!" in stdout
assert "Goodbye!" in stdout
def test_user_decorator_combined_with_builtin(self):
code, stdout, stderr = run_ct('''
class Commands {
cmds = {}
func register (name, handler) {
this.cmds.set (name, handler)
}
func run (name) {
if this.cmds.has (name) {
handler = this.cmds.get (name)
handler ()
}
}
}
cmds = new Commands ()
@cmds.register ("test")
@log
func test_cmd () {
print ("Testing")
}
cmds.run ("test")
''')
assert code == 0
assert "Testing" in stdout
class TestTypeAnnotations:
def test_typed_variables_run(self):
code, stdout, _ = run_ct('''
name: string = "Alice"
age: int = 30
print ("{name} is {age}")
''')
assert code == 0
assert "Alice is 30" in stdout
def test_typed_function_params(self):
code, stdout, _ = run_ct('''
func greet (name: string, age: int): string {
return "Hello, {name}! Age: {age}"
}
print (greet ("Bob", 25))
''')
assert code == 0
assert "Hello, Bob! Age: 25" in stdout
def test_typed_class_fields(self):
code, stdout, _ = run_ct('''
class User {
name: string = ""
age: int = 0
construct (name: string, age: int) {
this.name = name
this.age = age
}
}
u = new User ("Charlie", 35)
print ("{u.name} ({u.age})")
''')
assert code == 0
assert "Charlie (35)" in stdout
def test_type_error_string_to_int(self):
code, stdout, stderr = compile_ct_with_flags('x: int = "hello"')
assert code == 1
assert "Type mismatch" in stderr
assert "expected 'int'" in stderr
assert "got 'string'" in stderr
def test_type_error_int_to_array(self):
code, stdout, stderr = compile_ct_with_flags('arr: array = 42')
assert code == 1
assert "Type mismatch" in stderr
def test_warn_types_flag(self):
code, stdout, stderr = compile_ct_with_flags('x: int = "hello"', ['--warn-types'])
assert code == 0
assert "Warning: Type mismatch" in stderr
def test_no_type_check_flag(self):
code, stdout, stderr = compile_ct_with_flags('x: int = "hello"', ['--no-type-check'])
assert code == 0
assert "Type mismatch" not in stderr
def test_typed_array_param_works(self):
code, stdout, _ = run_ct('''
func sum_array (arr: array): int {
total = 0
foreach item in arr {
total += item
}
return total
}
nums = [1, 2, 3, 4, 5]
print (sum_array (nums))
''')
assert code == 0
assert "15" in stdout
def test_correct_types_no_error(self):
code, stdout, stderr = compile_ct_with_flags('''
name: string = "test"
count: int = 42
flag: bool = true
items: array = [1, 2, 3]
config: dict = {"key": "value"}
''')
assert code == 0
assert "Type mismatch" not in stderr
from helpers import run_ct
class TestFunctions:
def test_function_call(self):
code, stdout, _ = run_ct('''
func greet () {
print ("hello")
}
greet ()
''')
assert code == 0
assert "hello" in stdout
def test_function_with_param(self):
code, stdout, _ = run_ct('''
func greet (name) {
print ("Hello, {name}")
}
greet ("Alice")
''')
assert code == 0
assert "Hello, Alice" in stdout
def test_function_return(self):
code, stdout, _ = run_ct('''
func add (a, b) {
return a + b
}
result = add (3, 4)
print (result)
''')
assert code == 0
assert "7" in stdout
def test_function_default_param(self):
code, stdout, _ = run_ct('''
func greet (name = "World") {
print ("Hello, {name}")
}
greet ()
''')
assert code == 0
assert "Hello, World" in stdout
class TestLambdas:
def test_simple_lambda(self):
code, stdout, _ = run_ct('''
double = x => x * 2
print (double (5))
''')
assert code == 0
assert "10" in stdout
def test_multi_param_lambda(self):
code, stdout, _ = run_ct('''
add = (a, b) => a + b
print (add (3, 4))
''')
assert code == 0
assert "7" in stdout
class TestCallbackVariables:
def test_lambda_assigned_and_called(self):
code, stdout, _ = run_ct('''
doubler = x => x * 2
result = doubler (5)
print (result)
''')
assert code == 0
assert "10" in stdout
def test_typed_callback_variable(self):
code, stdout, _ = run_ct('''
tripler: (int) => int = x => x * 3
result = tripler (4)
print (result)
''')
assert code == 0
assert "12" in stdout
def test_callback_passed_to_function(self):
code, stdout, _ = run_ct('''
func apply (callback, value) {
return callback (value)
}
double = x => x * 2
result = apply (double, 7)
print (result)
''')
assert code == 0
assert "14" in stdout
def test_callback_with_multiple_uses(self):
code, stdout, _ = run_ct('''
square = x => x * x
a = square (3)
b = square (4)
c = square (5)
print ("{a} {b} {c}")
''')
assert code == 0
assert "9 16 25" in stdout
def test_typed_callback_passed_to_function(self):
code, stdout, _ = run_ct('''
func applyTwice (f: (int) => int, x: int): int {
return f (f (x))
}
double: (int) => int = x => x * 2
result = applyTwice (double, 3)
print (result)
''')
assert code == 0
assert "12" in stdout
class TestCallbacks:
def test_callback_function_parameter(self):
code, stdout, _ = run_ct('''
func apply (callback, value) {
return callback (value)
}
func double (x) {
return x * 2
}
result = apply (double, 5)
print ("Result: {result}")
''')
assert code == 0
assert "Result: 10" in stdout
def test_lambda_as_callback(self):
code, stdout, _ = run_ct('''
func apply (callback, value) {
return callback (value)
}
triple = x => x * 3
result = apply (triple, 4)
print ("Result: {result}")
''')
assert code == 0
assert "Result: 12" in stdout
def test_inline_lambda_callback(self):
code, stdout, _ = run_ct('''
func apply (callback, value) {
return callback (value)
}
result = apply (x => x + 10, 5)
print ("Result: {result}")
''')
assert code == 0
assert "Result: 15" in stdout
def test_callback_with_multiple_args(self):
code, stdout, _ = run_ct('''
func compute (fn, a, b) {
return fn (a, b)
}
add = (x, y) => x + y
result = compute (add, 3, 7)
print ("Result: {result}")
''')
assert code == 0
assert "Result: 10" in stdout
def test_callback_in_class_method(self):
code, stdout, _ = run_ct('''
class Processor {
func process (callback, value) {
return callback (value)
}
}
p = new Processor ()
square = x => x * x
result = p.process (square, 5)
print ("Result: {result}")
''')
assert code == 0
assert "Result: 25" in stdout
def test_callback_chain(self):
code, stdout, _ = run_ct('''
func apply (fn, value) {
return fn (value)
}
double = x => x * 2
add_one = x => x + 1
result = apply (add_one, apply (double, 5))
print ("Result: {result}")
''')
assert code == 0
assert "Result: 11" in stdout
class TestFunctionParameterPassing:
def test_array_modification_in_function(self):
code, stdout, _ = run_ct('''
func modify_arr (arr) {
arr.push (99)
arr.push (100)
}
nums = [1, 2, 3]
print ("Before: {nums.len ()}")
modify_arr (nums)
print ("After: {nums.len ()}")
''')
assert code == 0
assert "Before: 3" in stdout
assert "After: 5" in stdout
def test_array_return_length_from_function(self):
code, stdout, _ = run_ct('''
func get_len (arr) {
return arr.len ()
}
nums = [1, 2, 3, 4, 5]
len = get_len (nums)
print ("Length: {len}")
''')
assert code == 0
assert "Length: 5" in stdout
def test_dict_modification_in_function(self):
code, stdout, _ = run_ct('''
func add_key (d, key, value) {
d.set (key, value)
}
config = {"host": "localhost"}
add_key (config, "port", "8080")
port = config.get ("port")
print ("Port: {port}")
''')
assert code == 0
assert "Port: 8080" in stdout
def test_dict_has_in_function(self):
code, stdout, _ = run_ct('''
func has_key (d, key) {
return d.has (key)
}
config = {"host": "localhost", "port": "8080"}
has_host = has_key (config, "host")
has_debug = has_key (config, "debug")
print ("Has host: {has_host}")
print ("Has debug: {has_debug}")
''')
assert code == 0
assert "Has host: true" in stdout
assert "Has debug: false" in stdout
def test_array_get_in_function(self):
code, stdout, _ = run_ct('''
func first_element (arr) {
return arr.get (0)
}
nums = [42, 100, 200]
first = first_element (nums)
print ("First: {first}")
''')
assert code == 0
assert "First: 42" in stdout
def test_array_slice_in_function(self):
code, stdout, _ = run_ct('''
func double_all (arr) {
for i in range (arr.len ()) {
val = arr.get (i)
arr.set (i, val * 2)
}
}
nums = [1, 2, 3]
double_all (nums)
print ("{nums.get (0)} {nums.get (1)} {nums.get (2)}")
''')
assert code == 0
assert "2 4 6" in stdout
def test_nested_function_array_passing(self):
code, stdout, _ = run_ct('''
func inner (arr) {
arr.push ("inner")
}
func outer (arr) {
arr.push ("outer")
inner (arr)
}
items = []
outer (items)
print ("Items: {items.len ()}")
''')
assert code == 0
assert "Items: 2" in stdout
def test_dict_keys_in_function(self):
code, stdout, _ = run_ct('''
func count_keys (d) {
keys = d.keys ()
return keys.len ()
}
config = {"a": "1", "b": "2", "c": "3"}
count = count_keys (config)
print ("Key count: {count}")
''')
assert code == 0
assert "Key count: 3" in stdout
def test_mixed_parameters_scalar_and_array(self):
code, stdout, _ = run_ct('''
func add_items (prefix, arr, count) {
for i in range (count) {
arr.push ("{prefix}_{i}")
}
}
items = []
add_items ("item", items, 3)
print ("Count: {items.len ()}")
''')
assert code == 0
assert "Count: 3" in stdout
def test_dict_get_in_function(self):
code, stdout, _ = run_ct('''
func get_value (d, key) {
if d.has (key) {
return d.get (key)
}
return ""
}
data = {"name": "Alice", "age": "30"}
name = get_value (data, "name")
print ("Name: {name}")
''')
assert code == 0
assert "Name: Alice" in stdout
def test_array_foreach_in_function(self):
code, stdout, _ = run_ct('''
func sum_array (arr) {
total = 0
foreach n in arr {
total += n
}
return total
}
nums = [1, 2, 3, 4, 5]
result = sum_array (nums)
print ("Sum: {result}")
''')
assert code == 0
assert "Sum: 15" in stdout
def test_string_split_returns_array(self):
code, stdout, _ = run_ct('''
func count_words (text) {
words = text.split (" ")
return words.len ()
}
sentence = "hello world foo bar"
count = count_words (sentence)
print ("Word count: {count}")
''')
assert code == 0
assert "Word count: 4" in stdout
def test_array_slice_returns_array(self):
code, stdout, _ = run_ct('''
func first_two (arr) {
sub = arr.slice (0, 2)
return sub.len ()
}
nums = [1, 2, 3, 4, 5]
count = first_two (nums)
print ("Slice len: {count}")
''')
assert code == 0
assert "Slice len: 2" in stdout
from helpers import run_ct, compile_ct_check
class TestStringMethods:
def test_upper(self):
code, stdout, _ = run_ct('''
s = "hello"
print (s.upper ())
''')
assert code == 0
assert "HELLO" in stdout
def test_lower(self):
code, stdout, _ = run_ct('''
s = "HELLO"
print (s.lower ())
''')
assert code == 0
assert "hello" in stdout
def test_contains(self):
code, stdout, _ = run_ct('''
s = "hello world"
if s.contains ("world") {
print ("yes")
}
''')
assert code == 0
assert "yes" in stdout
class TestMethodChaining:
def test_function_result_chaining(self):
code, stdout, _ = run_ct('''
func getValue () {
return "hello"
}
result = getValue ().upper ()
print (result)
''')
assert code == 0
assert "HELLO" in stdout
def test_class_method_chaining(self):
code, stdout, _ = run_ct('''
class Data {
construct () {}
func getText () {
return "hello world"
}
}
d = new Data ()
result = d.getText ().upper ()
print (result)
''')
assert code == 0
assert "HELLO WORLD" in stdout
def test_triple_chaining(self):
code, stdout, _ = run_ct('''
class Data {
construct () {}
func getText () {
return " hello "
}
}
d = new Data ()
result = d.getText ().trim ().upper ()
print (result)
''')
assert code == 0
assert "HELLO" in stdout
def test_dict_method_chaining(self):
code, stdout, _ = run_ct('''
d = {"name": "john"}
result = d.get ("name").upper ()
print (result)
''')
assert code == 0
assert "JOHN" in stdout
def test_array_method_chaining(self):
code, stdout, _ = run_ct('''
arr = ["hello", "world"]
result = arr.get (0).upper ()
print (result)
''')
assert code == 0
assert "HELLO" in stdout
class TestArrays:
def test_array_create(self):
code, stdout, _ = run_ct('''
arr = [1, 2, 3]
print (arr[0])
''')
assert code == 0
assert "1" in stdout
def test_array_push(self):
code, stdout, _ = run_ct('''
arr = [1, 2]
arr.push (3)
print (arr.len ())
''')
assert code == 0
assert "3" in stdout
class TestArrayMapFilter:
def test_array_map_simple(self):
code, stdout, _ = run_ct('''
arr = [1, 2, 3]
result = arr.map (x => x * 2)
print (result.join (" "))
''')
assert code == 0
assert "2 4 6" in stdout
def test_array_map_square(self):
code, stdout, _ = run_ct('''
arr = [1, 2, 3, 4]
squared = arr.map (x => x * x)
print (squared.join (" "))
''')
assert code == 0
assert "1 4 9 16" in stdout
def test_array_filter_even(self):
code, stdout, _ = run_ct('''
arr = [1, 2, 3, 4, 5, 6]
evens = arr.filter (x => x % 2 == 0)
print (evens.join (" "))
''')
assert code == 0
assert "2 4 6" in stdout
def test_array_filter_greater_than(self):
code, stdout, _ = run_ct('''
arr = [5, 10, 15, 20]
big = arr.filter (x => x > 10)
print (big.join (" "))
''')
assert code == 0
assert "15 20" in stdout
class TestUrlencode:
def test_urlencode_simple(self):
code, stdout, _ = run_ct('''
text = "hello world"
encoded = text.urlencode ()
print (encoded)
''')
assert code == 0
assert "hello%20world" in stdout
def test_urlencode_special_chars(self):
code, stdout, _ = run_ct('''
text = "a=b&c=d"
encoded = text.urlencode ()
print (encoded)
''')
assert code == 0
assert "%3D" in stdout or "%3d" in stdout
assert "%26" in stdout
def test_urlencode_cyrillic(self):
code, stdout, _ = run_ct('''
text = "привет"
encoded = text.urlencode ()
print (encoded)
''')
assert code == 0
assert "%" in stdout
assert "привет" not in stdout
def test_urlencode_empty(self):
code, stdout, _ = run_ct('''
text = ""
encoded = text.urlencode ()
print ("result: {encoded}")
''')
assert code == 0
assert "result:" in stdout
class TestMethodValidation:
def test_unknown_array_method(self):
code, stdout, stderr = compile_ct_check('''
arr = [1, 2, 3]
x = arr.nonexistent ()
''')
assert code != 0
assert "Unknown method 'nonexistent'" in stderr
assert "array" in stderr
def test_unknown_dict_method(self):
code, stdout, stderr = compile_ct_check('''
d = {"key": "value"}
x = d.nonexistent ()
''')
assert code != 0
assert "Unknown method 'nonexistent'" in stderr
assert "dict" in stderr
def test_unknown_namespace_method(self):
code, stdout, stderr = compile_ct_check('''
x = fs.nonexistent ()
''')
assert code != 0
assert "Unknown method 'nonexistent'" in stderr
assert "fs" in stderr
def test_valid_string_methods(self):
code, stdout, stderr = compile_ct_check('''
text = "hello"
a = text.upper ()
b = text.lower ()
c = text.len ()
d = text.trim ()
e = text.urlencode ()
''')
assert code == 0
def test_valid_array_methods(self):
code, stdout, stderr = compile_ct_check('''
arr = [1, 2, 3]
arr.push (4)
x = arr.pop ()
y = arr.len ()
z = arr.join (" ")
''')
assert code == 0
def test_valid_dict_methods(self):
code, stdout, stderr = compile_ct_check('''
d = {"key": "value"}
a = d.get ("key")
d.set ("key2", "val2")
b = d.has ("key")
c = d.keys ()
''')
assert code == 0
def test_valid_namespace_methods(self):
code, stdout, stderr = compile_ct_check('''
x = math.abs (-5)
y = math.max (1, 2)
''')
assert code == 0
def test_error_shows_available_methods(self):
code, stdout, stderr = compile_ct_check('''
arr = [1, 2, 3]
x = arr.foo ()
''')
assert code != 0
assert "Available:" in stderr
assert "push" in stderr
assert "pop" in stderr
from helpers import run_ct
class TestShellCommands:
def test_shell_cmd_statement(self):
code, stdout, stderr = run_ct('echo ("hello from shell")')
assert code == 0
assert "hello from shell" in stdout
def test_shell_cmd_assignment(self):
code, stdout, stderr = run_ct('''
result = echo ("hello capture")
print (result)
''')
assert code == 0
assert "hello capture" in stdout
def test_shell_cmd_with_flags(self):
code, stdout, stderr = run_ct('''
result = echo ("-n", "no newline")
print (result)
''')
assert code == 0
assert "no newline" in stdout
def test_shell_cmd_date(self):
code, stdout, stderr = run_ct('''
ts = date ("+%s")
print (ts)
''')
assert code == 0
assert stdout.strip().isdigit()
def test_shell_pipe_two_cmds(self):
code, stdout, stderr = run_ct('''
result = echo ("aaa bbb ccc") | wc ("-w")
print (result)
''')
assert code == 0
assert "3" in stdout
def test_shell_pipe_three_cmds(self):
code, stdout, stderr = run_ct(r'''
result = printf ("alpha\nbeta\ngamma") | sort ("-r") | head ("-1")
print (result)
''')
assert code == 0
assert "gamma" in stdout
def test_shell_pipe_grep(self):
code, stdout, stderr = run_ct(r'''
result = printf ("foo\nbar\nbaz") | grep ("ba")
print (result)
''')
assert code == 0
assert "bar" in stdout
assert "baz" in stdout
assert "foo" not in stdout
def test_mixed_pipe_ct_func_to_shell(self):
code, stdout, stderr = run_ct(r'''
func generate () {
print ("line one")
print ("line two")
print ("line three")
}
result = generate () | grep ("two")
print (result)
''')
assert code == 0
assert "line two" in stdout
assert "line one" not in stdout
def test_mixed_pipe_ct_func_to_shell_stmt(self):
code, stdout, stderr = run_ct(r'''
func generate () {
print ("hello world")
print ("goodbye world")
}
generate () | grep ("hello")
''')
assert code == 0
assert "hello world" in stdout
assert "goodbye" not in stdout
def test_ct_func_not_treated_as_shell(self):
code, stdout, stderr = run_ct('''
func double (x) {
return x * 2
}
result = double (21)
print (result)
''')
assert code == 0
assert "42" in stdout
def test_callback_not_treated_as_shell(self):
code, stdout, stderr = run_ct('''
func apply (callback, value) {
return callback (value)
}
func triple (x) { return x * 3 }
result = apply (triple, 7)
print (result)
''')
assert code == 0
assert "21" in stdout
def test_legacy_shell_exec(self):
code, stdout, stderr = run_ct('''
result = shell.exec ("echo legacy") | shell.exec ("tr a-z A-Z")
print (result)
''')
assert code == 0
assert "LEGACY" in stdout
def test_legacy_shell_capture(self):
code, stdout, stderr = run_ct('''
result = shell.capture ("echo captured")
print (result)
''')
assert code == 0
assert "captured" in stdout
def test_shell_cmd_in_interpolation(self):
code, stdout, stderr = run_ct('''
name = whoami ()
print ("user: {name}")
''')
assert code == 0
assert "user: " in stdout
assert len(stdout.strip().split(": ")[1]) > 0
def test_shell_pipe_with_sed(self):
code, stdout, stderr = run_ct('''
result = echo ("hello world") | sed ("s/world/content/")
print (result)
''')
assert code == 0
assert "hello content" in stdout
def test_shell_cmd_no_args(self):
code, stdout, stderr = run_ct('''
result = pwd ()
print (result)
''')
assert code == 0
assert "/" in stdout
def test_mixed_pipe_multiple_ct_and_shell(self):
code, stdout, stderr = run_ct(r'''
func make_lines () {
print ("apple")
print ("banana")
print ("cherry")
}
result = make_lines () | sort ("-r") | head ("-2")
print (result)
''')
assert code == 0
assert "cherry" in stdout
assert "banana" in stdout
def test_shell_cmd_in_if_condition(self):
code, stdout, stderr = run_ct('''
count = echo ("hello") | wc ("-c")
if count > 0 {
print ("not empty")
}
''')
assert code == 0
assert "not empty" in stdout
def test_shell_cmd_in_loop(self):
code, stdout, stderr = run_ct('''
for i in range (1, 4) {
result = echo ("line {i}")
print ("got: {result}")
}
''')
assert code == 0
assert "got: line 1" in stdout
assert "got: line 2" in stdout
assert "got: line 3" in stdout
def test_shell_cmd_in_function(self):
code, stdout, stderr = run_ct('''
func get_host () {
return hostname ()
}
h = get_host ()
print (h)
''')
assert code == 0
assert len(stdout.strip()) > 0
from helpers import run_ct, compile_ct
class TestStdlib:
def test_len_string(self):
code, stdout, _ = run_ct('''
s = "hello"
print (len (s))
''')
assert code == 0
assert "5" in stdout
def test_math_abs(self):
code, stdout, _ = run_ct('''
print (math.abs (-5))
''')
assert code == 0
assert "5" in stdout
def test_range(self):
code, stdout, _ = run_ct('''
foreach i in range (1, 4) {
print (i)
}
''')
assert code == 0
assert "1" in stdout
assert "2" in stdout
assert "3" in stdout
class TestEnvVariables:
def test_env_home(self):
code, stdout, _ = run_ct('''
home = env.HOME
print (home)
''')
assert code == 0
assert "/home" in stdout or "/Users" in stdout or "/root" in stdout
def test_env_user(self):
code, stdout, _ = run_ct('''
user = env.USER
print (user)
''')
assert code == 0
assert len(stdout.strip()) > 0
def test_env_typed(self):
code, stdout, _ = run_ct('''
home: string = env.HOME
print (home)
''')
assert code == 0
assert "/" in stdout
def test_env_int_arithmetic(self):
code, stdout, _ = run_ct('''
uid: int = env.UID
doubled = uid * 2
print (doubled)
''')
assert code == 0
assert int(stdout.strip()) > 0
def test_env_set(self):
code, stdout, _ = run_ct('''
env.MY_TEST_VAR = "hello"
print (env.MY_TEST_VAR)
''')
assert code == 0
assert "hello" in stdout
def test_env_set_with_interpolation(self):
code, stdout, _ = run_ct('''
name = "world"
env.GREETING = "Hello, {name}!"
print (env.GREETING)
''')
assert code == 0
assert "Hello, world!" in stdout
class TestJson:
def test_json_parse(self):
code, stdout, _ = run_ct(r'''
json_str = "\{\"name\": \"Alice\", \"age\": 30\}"
data = json.parse (json_str)
print (data.get ("name"))
print (data.get ("age"))
''')
assert code == 0
assert "Alice" in stdout
assert "30" in stdout
def test_json_parse_set(self):
code, stdout, _ = run_ct(r'''
json_str = "\{\"x\": 1\}"
data = json.parse (json_str)
data.set ("y", 2)
print (data.get ("x"))
print (data.get ("y"))
''')
assert code == 0
assert "1" in stdout
assert "2" in stdout
def test_json_stringify(self):
code, stdout, _ = run_ct(r'''
json_str = "\{\"name\": \"Bob\"\}"
data = json.parse (json_str)
data.set ("age", 25)
result = json.stringify (data)
print (result)
''')
assert code == 0
assert "name" in stdout
assert "Bob" in stdout
assert "age" in stdout
assert "25" in stdout
def test_json_has(self):
code, stdout, _ = run_ct(r'''
json_str = "\{\"key\": \"value\"\}"
data = json.parse (json_str)
print (data.has ("key"))
print (data.has ("missing"))
''')
assert code == 0
assert "true" in stdout
assert "false" in stdout
class TestJsonGet:
def test_json_get_simple(self):
code, stdout, _ = run_ct(r'''
json_str = "\{\"name\": \"Alice\"\}"
result = json.get (json_str, ".name")
print (result)
''')
assert code == 0
assert "Alice" in stdout
def test_json_get_nested(self):
code, stdout, _ = run_ct(r'''
json_str = "\{\"user\": \{\"name\": \"Bob\", \"age\": 25\}\}"
name = json.get (json_str, ".user.name")
age = json.get (json_str, ".user.age")
print (name)
print (age)
''')
assert code == 0
assert "Bob" in stdout
assert "25" in stdout
def test_json_get_array(self):
code, stdout, _ = run_ct(r'''
json_str = "\{\"items\": [1, 2, 3]\}"
first = json.get (json_str, ".items[0]")
print (first)
''')
assert code == 0
assert "1" in stdout
def test_json_get_length(self):
code, stdout, _ = run_ct(r'''
json_str = "\{\"items\": [1, 2, 3, 4, 5]\}"
count = json.get (json_str, ".items | length")
print (count)
''')
assert code == 0
assert "5" in stdout
class TestFileHandles:
def test_fs_open_write_close(self):
code, stdout, _ = run_ct('''
path = "/tmp/ct_test_fh.txt"
f = fs.open (path, "w")
f.write ("hello world")
f.close ()
content = fs.read (path)
print (content)
fs.remove (path)
''')
assert code == 0
assert "hello world" in stdout
def test_fs_open_read_close(self):
code, stdout, _ = run_ct('''
path = "/tmp/ct_test_fh2.txt"
fs.write (path, "test content")
f = fs.open (path, "r")
data = f.read ()
f.close ()
print (data)
fs.remove (path)
''')
assert code == 0
assert "test content" in stdout
class TestWithStatement:
def test_with_single_resource(self):
code, stdout, _ = run_ct('''
path = "/tmp/ct_with_test.txt"
fs.write (path, "test content")
with f in fs.open (path) {
data = f.read ()
print (data)
}
fs.remove (path)
''')
assert code == 0
assert "test content" in stdout
def test_with_auto_close(self):
code, bash_output, _ = compile_ct('''
with f in fs.open ("/tmp/test.txt") {
data = f.read ()
}
''')
assert code == 0
assert "__ct_fh___exit__" in bash_output
def test_with_multiple_resources(self):
code, stdout, _ = run_ct('''
src = "/tmp/ct_src.txt"
dst = "/tmp/ct_dst.txt"
fs.write (src, "copy me")
with input, output in fs.open (src), fs.open (dst, "w") {
data = input.read ()
output.write (data)
}
result = fs.read (dst)
print (result)
fs.remove (src)
fs.remove (dst)
''')
assert code == 0
assert "copy me" in stdout
class TestExceptionHandling:
def test_try_except(self):
code, stdout, _ = run_ct('''
try {
throw "oops"
} except {
print ("caught")
}
''')
assert code == 0
assert "caught" in stdout
def test_defer(self):
code, stdout, _ = run_ct('''
func test () {
defer print ("cleanup")
print ("work")
}
test ()
''')
assert code == 0
lines = stdout.strip().split('\n')
assert "work" in lines[0]
assert "cleanup" in lines[1]
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment