#! /usr/bin/env/python
# -*- coding: utf-8 -*-
# cython: language_level=3, always_allow_keywords=True

## Copyright 2009-2014 by LivingLogic AG, Bayreuth/Germany
## Copyright 2009-2014 by Walter Dörwald
##
## All Rights Reserved
##
## See ll/xist/__init__.py for the license


import sys, os, re, datetime, io, tempfile, collections, shutil, subprocess

import pytest

from ll import ul4c, color, misc, ul4on
from ll.xist.ns import html, ul4


class PseudoDict(collections.Mapping):
	def __init__(self, dict):
		self.dict = dict

	def __getitem__(self, key):
		return self.dict[key]

	def __iter__(self):
		return iter(self.dict)

	def __len__(self):
		return len(self.dict)


class PseudoList(collections.Sequence):
	def __init__(self, list):
		self.list = list

	def __getitem__(self, index):
		return self.list[index]

	def __len__(self):
		return len(self.list)


def render_python(__, *, keepws=True, **variables):
	"""
	Compile the template from the source ``__`` and render it with the variables ``variables``.
	"""
	template = ul4c.Template(__, keepws=keepws)
	return template.renders(**variables)


def render_python_dumps(__, *, keepws=True, **variables):
	"""
	Compile the template from the source ``__``, create a string dump from it,
	recreate the template from the dump string and render it with the variables
	``variables``.
	"""
	template = ul4c.Template(__, keepws=keepws)
	template = ul4c.Template.loads(template.dumps()) # Recreate the template from the binary dump
	return template.renders(**variables)


def render_python_dump(__, *, keepws=True, **variables):
	"""
	Compile the template from the source ``__``, dump it to a stream, recreate
	the template from the dump and render it with the variables ``variables``.
	"""
	template = ul4c.Template(__, keepws=keepws)
	stream = io.StringIO()
	template.dump(stream)
	stream.seek(0)
	template = ul4c.Template.load(stream) # Recreate the template from the stream
	return template.renders(**variables)


def render_js(__, *, keepws=True, **variables):
	"""
	Compile the template from the source ``__``, and generate Javascript source
	from it that renders the template with the variables ``variables``.

	(this requires an installed ``d8`` shell from V8 (http://code.google.com/p/v8/))
	"""
	template = ul4c.Template(__, keepws=keepws)
	js = template.jssource()
	js = "template = {};\ndata = {};\nprint(template.renders(data));\n".format(js, ul4c._asjson(variables))
	with tempfile.NamedTemporaryFile(mode="wb", suffix=".js") as f:
		f.write(js.encode("utf-8"))
		f.flush()
		dir = os.path.expanduser("~/checkouts/LivingLogic.Javascript.ul4")
		proc = subprocess.Popen("d8 {dir}/ul4on.js {dir}/ul4.js {fn}".format(dir=dir, fn=f.name), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
		(stdout, stderr) = proc.communicate()
	stdout = stdout.decode("utf-8")
	stderr = stderr.decode("utf-8")
	# Check if we have an exception
	if proc.returncode:
		print(stdout, file=sys.stdout)
		print(stderr, file=sys.stderr)
		raise RuntimeError((stderr or stdout).splitlines()[0])
	return stdout[:-1] # Drop the "\n"


def render_php(__, **variables):
	template = ul4c.Template(__)
	php = r"""<?php
	include_once 'com/livinglogic/ul4/ul4.php';
	$template = \com\livinglogic\ul4\InterpretedTemplate::loads({});
	$variables = {};
	print $template->renders($variables);
	?>""".format(phpexpr(template.dumps()), phpexpr(variables))
	with tempfile.NamedTemporaryFile(mode="wb", suffix=".php") as f:
		f.write(php.encode("utf-8"))
		f.flush()
		dir = os.path.expanduser("~/checkouts/LivingLogic.PHP.ul4")
		proc = subprocess.Popen("php -n -d include_path={dir} -d date.timezone=Europe/Berlin {fn}".format(dir=dir, fn=f.name), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
		(stdout, stderr) = proc.communicate()
	stdout = stdout.decode("utf-8")
	stderr = stderr.decode("utf-8")
	# Check if we have an exception
	if proc.returncode:
		print(stdout, file=sys.stdout)
		print(stderr, file=sys.stderr)
		raise RuntimeError((stderr.strip() or stdout.strip()).splitlines()[0])
	return stdout


def phpexpr(obj):
	if obj is None:
		return "null"
	elif isinstance(obj, bool):
		return "true" if obj else "false"
	elif isinstance(obj, int):
		return str(obj)
	elif isinstance(obj, float):
		return str(obj)
	elif isinstance(obj, str):
		v = ['"']
		for c in obj:
			if c == '\n':
				c = '\\n'
			elif c == '\t':
				c = '\\t'
			elif c == '"':
				c = '\\"'
			elif ord(c) < 32:
				c = '\\x{:02x}'.format(ord(c))
			v.append(c)
		v.append('"')
		return "".join(v)
	elif isinstance(obj, datetime.datetime):
		return r"\com\livinglogic\ul4\Utils::date({}, {}, {}, {}, {}, {}, {})".format(obj.year, obj.month, obj.day, obj.hour, obj.minute, obj.second, obj.microsecond)
	elif isinstance(obj, datetime.date):
		return r"\com\livinglogic\ul4\Utils::date({}, {}, {})".format(obj.year, obj.month, obj.day)
	elif isinstance(obj, datetime.timedelta):
		return r"new \com\livinglogic\ul4\TimeDelta({}, {}, {})".format(obj.days, obj.seconds, obj.microseconds)
	elif isinstance(obj, misc.monthdelta):
		return r"new \com\livinglogic\ul4\MonthDelta({})".format(obj.months)
	elif isinstance(obj, color.Color):
		return r"new \com\livinglogic\ul4\Color({}, {}, {}, {})".format(obj.r(), obj.g(), obj.b(), obj.a())
	elif isinstance(obj, ul4c.Template):
		return r"\com\livinglogic\ul4\InterpretedTemplate::loads({})".format(phpexpr(obj.dumps()))
	elif isinstance(obj, collections.Mapping):
		return "array({})".format(", ".join("{} => {}".format(phpexpr(key), phpexpr(value)) for (key, value) in obj.items()))
	elif isinstance(obj, collections.Sequence):
		return "array({})".format(", ".join(phpexpr(item) for item in obj))
	else:
		raise ValueError("Can't convert {!r} to PHP".format(obj))


def java_findexception(output):
	lines = output.splitlines()
	msg = None
	for line in lines:
		prefix1 = 'Exception in thread "main"'
		prefix2 = "Caused by:"
		if line.startswith(prefix1):
			msg = line[len(prefix1):].strip()
		elif line.startswith(prefix2):
			msg = line[len(prefix2):].strip()
	if msg is not None:
		print(output, file=sys.stderr)
		raise RuntimeError(msg)


def java_formatsource(string):
	"""
	Reindents the Java source.
	"""
	indent = 0
	newlines = []
	for line in string.strip().splitlines(False):
		line = line.strip()
		if line in {"}", ")", "};", "},", ");", "),"}:
			indent -= 1
		if line:
			newlines.append(indent*"\t" + line + "\n")
		if line == "{" or line.endswith("("):
			indent += 1
	return "".join(newlines)


def java_runsource(source):
	"""
	Compile the Java source :obj:`source`, run it and return the output
	"""
	maincodetemplate = """
	public class UL4Test
	{
		@SuppressWarnings("unchecked")
		public static void main(String[] args) throws java.io.IOException, java.io.UnsupportedEncodingException, org.antlr.runtime.RecognitionException
		{
			%(source)s
		}
	}
	"""

	tempdir = tempfile.mkdtemp()
	try:
		source = maincodetemplate % dict(source=source)
		source = java_formatsource(source)
		with open(os.path.join(tempdir, "UL4Test.java"), "wb") as f:
			f.write(source.encode("utf-8"))
		proc = subprocess.Popen("cd {}; javac -encoding utf-8 UL4Test.java".format(tempdir), stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
		(stdout, stderr) = proc.communicate()
		if proc.returncode:
			stderr = stderr.decode("utf-8")
			print(stderr, file=sys.stderr)
			raise RuntimeError(stderr.splitlines()[0])
		proc = subprocess.Popen("cd {}; java UL4Test".format(tempdir), stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
		(stdout, stderr) = proc.communicate()
		# Check if we have an exception
		java_findexception(stderr.decode("utf-8"))
	finally:
		shutil.rmtree(tempdir)
	if stderr:
		print(stderr, file=sys.stderr)
	return stdout.decode("utf-8")



def render_java_interpretedtemplate_by_python(__, *, keepws=True, **variables):
	"""
	Compile the template from the source ``__``, and generate Java source that
	recreates the template from the Python generated dump and renders the
	template with the variables ``variables``.

	(this requires an installed Java compiler and the Java UL4 jar)
	"""

	codetemplate = """
	com.livinglogic.ul4.InterpretedTemplate template = %(template)s;
	java.util.Map<String, Object> variables = %(variables)s;
	String output = template.renders(variables);
	// We can't use ``System.out.print`` here, because this gives us no control over the encoding
	// Use ``System.out.write`` to make sure the output is in UTF-8
	byte[] outputBytes = output.getBytes("utf-8");
	System.out.write(outputBytes, 0, outputBytes.length);
	"""

	templatesource = ul4c.Template(__, keepws=keepws).javasource()
	java = codetemplate % dict(variables=misc.javaexpr(variables), template=templatesource)
	return java_runsource(java)


def render_java_interpretedtemplate_by_java(__, keepws=True, **variables):
	"""
	Generate Java source that compiles the template source ``__`` and renders the
	template with the variables ``variables``.

	(this requires an installed Java compiler and the Java UL4 jar)
	"""

	codetemplate = """
	com.livinglogic.ul4.InterpretedTemplate template = new com.livinglogic.ul4.InterpretedTemplate(%(source)s, %(keepws)s);
	java.util.Map<String, Object> variables = %(variables)s;
	String output = template.renders(variables);
	// We can't use ``System.out.print`` here, because this gives us no control over the encoding
	// Use ``System.out.write`` to make sure the output is in UTF-8
	byte[] outputBytes = output.getBytes("utf-8");
	System.out.write(outputBytes, 0, outputBytes.length);
	"""

	java = codetemplate % dict(source=misc.javaexpr(__), variables=misc.javaexpr(variables), keepws=misc.javaexpr(keepws))
	return java_runsource(java)


def call_python(__, *, keepws=True, **variables):
	"""
	Compile the template from the source ``__``, call it as a function with the variables ``variables`` and return the result.
	"""
	template = ul4c.Template(__, keepws=keepws)
	return template(**variables)


def call_python_dumps(__, *, keepws=True, **variables):
	"""
	Compile the template from the source ``__``, create a string dump from it,
	recreate the template from the dump string, call it as a function with the
	variables ``variables`` and return the result.
	"""
	template = ul4c.Template(__, keepws=keepws)
	template = ul4c.Template.loads(template.dumps()) # Recreate the template from the binary dump
	return template(**variables)


def call_python_dump(__, *, keepws=True, **variables):
	"""
	Compile the template from the source ``__``, dump it to a stream, recreate
	the template from the dump, call it as a function with the variables
	``variables`` and return the result.
	"""
	template = ul4c.Template(__, keepws=keepws)
	stream = io.StringIO()
	template.dump(stream)
	stream.seek(0)
	template = ul4c.Template.load(stream) # Recreate the template from the stream
	return template(**variables)


def call_js(__, *, keepws=True, **variables):
	"""
	Compile the template from the source ``__``, and generate Javascript source
	from it and call it as a function with the variables ``variables``.

	(this requires an installed ``d8`` shell from V8 (http://code.google.com/p/v8/))
	"""
	template = ul4c.Template(__, keepws=keepws)
	js = template.jssource()
	js = "template = {};\ndata = {};\nprint(ul4on.dumps(template.call(data)));\n".format(js, ul4c._asjson(variables))
	with tempfile.NamedTemporaryFile(mode="wb", suffix=".js") as f:
		f.write(js.encode("utf-8"))
		f.flush()
		dir = os.path.expanduser("~/checkouts/LivingLogic.Javascript.ul4")
		proc = subprocess.Popen("d8 {dir}/ul4on.js {dir}/ul4.js {fn}".format(dir=dir, fn=f.name), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
		(stdout, stderr) = proc.communicate()
	stdout = stdout.decode("utf-8")
	stderr = stderr.decode("utf-8")
	# Check if we have an exception
	if proc.returncode:
		print(stdout, file=sys.stdout)
		print(stderr, file=sys.stderr)
		raise RuntimeError((stderr or stdout).splitlines()[0])
	return ul4on.loads(stdout)


def call_java_interpretedtemplate_by_python(__, *, keepws=True, **variables):
	"""
	Compile the function from the source ``__``, and generate Java source that
	recreates the function from the Python generated dump and executes the
	function with the variables ``variables``.

	(this requires an installed Java compiler and the Java UL4 jar)
	"""

	codetemplate = """
	com.livinglogic.ul4.InterpretedTemplate template = %(template)s;
	java.util.Map<String, Object> variables = %(variables)s;
	Object output = template.call(variables);
	// We can't use ``System.out.print`` here, because this gives us no control over the encoding
	// Use ``System.out.write`` to make sure the output is in UTF-8
	byte[] outputBytes = com.livinglogic.ul4on.Utils.dumps(output).getBytes("utf-8");
	System.out.write(outputBytes, 0, outputBytes.length);
	"""

	templatesource = ul4c.Template(__, keepws=keepws).javasource()
	java = codetemplate % dict(variables=misc.javaexpr(variables), template=templatesource)
	return ul4on.loads(java_runsource(java))


def call_java_interpretedtemplate_by_java(__, keepws=True, **variables):
	"""
	Generate Java source that compiles the function source ``__`` and executes the
	function with the variables ``variables``.

	(this requires an installed Java compiler and the Java UL4 jar)
	"""

	codetemplate = """
	com.livinglogic.ul4.InterpretedTemplate template = new com.livinglogic.ul4.InterpretedTemplate(%(source)s, %(keepws)s);
	java.util.Map<String, Object> variables = %(variables)s;
	Object output = template.call(variables);
	// We can't use ``System.out.print`` here, because this gives us no control over the encoding
	// Use ``System.out.write`` to make sure the output is in UTF-8
	byte[] outputBytes = com.livinglogic.ul4on.Utils.dumps(output).getBytes("utf-8");
	System.out.write(outputBytes, 0, outputBytes.length);
	"""

	java = codetemplate % dict(source=misc.javaexpr(__), variables=misc.javaexpr(variables), keepws=misc.javaexpr(keepws))
	return ul4on.loads(java_runsource(java))


all_renderers = dict(
	python=render_python,
	python_dumps=render_python_dumps,
	python_dump=render_python_dump,
	js=render_js,
	# php=render_php,
	java_interpreted_by_python=render_java_interpretedtemplate_by_python,
	java_interpreted_by_java=render_java_interpretedtemplate_by_java,
)

all_callers = dict(
	python=call_python,
	python_dumps=call_python_dumps,
	python_dump=call_python_dump,
	js=call_js,
	# php=call_php,
	java_interpreted_by_python=call_java_interpretedtemplate_by_python,
	java_interpreted_by_java=call_java_interpretedtemplate_by_java,
)


@pytest.fixture(scope="module", params=all_renderers.keys())
def r(request):
	return all_renderers[request.param]


@pytest.fixture(scope="module", params=all_callers.keys())
def c(request):
	return all_callers[request.param]


argumentmismatchmessage = [
	# Python argument mismatch exception messages
	"takes exactly \\d+ (positional )?arguments?", # < 3.3
	"got an unexpected keyword argument",
	"expected \\d+ arguments?",
	"Required argument .* not found",
	"takes exactly (one|\\d+) arguments?",
	"expected at least \\d+ arguments", # < 3.3
	"takes at most \\d+ (positional )?arguments?",
	"takes at least \\d+ argument", #  < 3.3
	"takes no arguments",
	"takes no keyword arguments",
	"expected at least \\d+ arguments?",
	"expected at most \\d+ arguments?, got \\d+",
	"missing \\d+ required positional arguments?", # 3.3
	"takes \\d+ positional arguments? but \\d+ (was|were) given", # 3.3
	"takes from \\d+ to \\d+ positional arguments but \\d+ (was|were) given", # 3.3
	# Javascript argument mismatch exception messages
	"requires (at least \\d+|\\d+(-\\d+)?) arguments?, \\d+ given",
	"required \\w+\\(\\) argument missing",
	# Java exception messages for argument mismatches
	"required \\w+\\(\\) argument \"\\w+\" \\(position \\d+\\) missing",
	"\\w+\\(\\) doesn't support an argument named \"\\w+\"",
	"\\w+\\(\\) doesn't support keyword arguments",
	"expects (at least \\d+|at most \\d+ positional|exactly \\d+|\\d+-\\d+) arguments?, \\d+ given",
]
argumentmismatchmessage = "({})".format("|".join(argumentmismatchmessage))


class raises(object):
	def __init__(self, msg):
		self.msg = re.compile(msg)

	def exceptionchain(self, exc):
		while exc is not None:
			yield exc
			exc = exc.__cause__

	def __enter__(self):
		pass

	def __exit__(self, type, value, traceback):
		if value is None:
			pytest.fail("failed to raise exception")
		# Check that any exception in the ``__cause__`` chain of the raised one matches a regexp
		exceptionmsgs = [str(exc) for exc in self.exceptionchain(value)]
		assert any(self.msg.search(msg) is not None for msg in exceptionmsgs)
		return True # Don't propagate exception


@pytest.mark.ul4
def test_text(r):
	assert 'gurk' == r('gurk')
	assert 'g\xfcrk' ==  r('g\xfcrk')
	assert 'gurk' == r('gurk', keepws=False)
	assert 'g\tu rk' == r('g\t\n\t u \n  r\n\t\tk', keepws=False)


@pytest.mark.ul4
def test_whitespace(r):
	assert "40"  == r("<?print\na\n+\nb\n?>", a=17, b=23)


@pytest.mark.ul4
def test_undefined(r):
	assert '' == r('<?print Undefined?>')
	assert 'no' == r('<?if Undefined?>yes<?else?>no<?end if?>')


@pytest.mark.ul4
def test_none(r):
	assert '' == r('<?print None?>')
	assert 'no' == r('<?if None?>yes<?else?>no<?end if?>')


@pytest.mark.ul4
def test_false(r):
	assert 'False' == r('<?print False?>')
	assert 'no' == r('<?if False?>yes<?else?>no<?end if?>')


@pytest.mark.ul4
def test_true(r):
	assert 'True' == r('<?print True?>')
	assert 'yes' == r('<?if True?>yes<?else?>no<?end if?>')


@pytest.mark.ul4
def test_int(r):
	values = (0, 42, -42, 0x7ffffff, 0x8000000, -0x8000000, -0x8000001)
	if r is not render_js and r is not render_php:
		# Since Javascript has no real integers the following would lead to rounding errors
		# And PHP doesn't have any support for big integers (except for some GMP wrappers, that may not be installed)
		values += (0x7ffffffffffffff, 0x800000000000000, -0x800000000000000, -0x800000000000001, 9999999999, -9999999999, 99999999999999999999, -99999999999999999999)
	for value in values:
		assert str(value) == r('<?print {}?>'.format(value))
	assert '255' == r('<?print 0xff?>')
	assert '255' == r('<?print 0Xff?>')
	assert '-255' == r('<?print -0xff?>')
	assert '-255' == r('<?print -0Xff?>')
	assert '63' == r('<?print 0o77?>')
	assert '63' == r('<?print 0O77?>')
	assert '-63' == r('<?print -0o77?>')
	assert '-63' == r('<?print -0O77?>')
	assert '7' == r('<?print 0b111?>')
	assert '7' == r('<?print 0B111?>')
	assert '-7' == r('<?print -0b111?>')
	assert '-7' == r('<?print -0B111?>')

	assert 'no' == r('<?if 0?>yes<?else?>no<?end if?>')
	assert 'yes' == r('<?if 1?>yes<?else?>no<?end if?>')
	assert 'yes' == r('<?if -1?>yes<?else?>no<?end if?>')


@pytest.mark.ul4
def test_float(r):
	# str() output might differ slightly between Python and JS, so eval the output again for tests
	assert 0.0 == eval(r('<?print 0.?>'))
	assert 42.0 == eval(r('<?print 42.?>'))
	assert -42.0 == eval(r('<?print -42.?>'))
	assert -42.5 == eval(r('<?print -42.5?>'))
	assert 1e42 == eval(r('<?print 1E42?>'))
	assert 1e42 == eval(r('<?print 1e42?>'))
	assert -1e42 == eval(r('<?print -1E42?>'))
	assert -1e42 == eval(r('<?print -1e42?>'))

	assert 'no' == r('<?if 0.?>yes<?else?>no<?end if?>')
	assert 'yes' == r('<?if 1.?>yes<?else?>no<?end if?>')
	assert 'yes' == r('<?if -1.?>yes<?else?>no<?end if?>')


@pytest.mark.ul4
def test_string(r):
	with raises("Unterminated string|mismatched character|MismatchedTokenException|NoViableAltException"):
		r('<?print "?>')
	assert 'foo' == r('<?print "foo"?>')
	assert '\n' == r('<?print "\\n"?>')
	assert '\r' == r('<?print "\\r"?>')
	assert '\t' == r('<?print "\\t"?>')
	assert '\f' == r('<?print "\\f"?>')
	assert '\b' == r('<?print "\\b"?>')
	assert '\a' == r('<?print "\\a"?>')
	assert '\x00' == r('<?print "\\x00"?>')
	assert '"' == r('<?print "\\""?>')
	assert "'" == r('<?print "\\\'"?>')
	assert '\u20ac' == r('<?print "\u20ac"?>')
	assert '\xff' == r('<?print "\\xff"?>')
	assert '\u20ac' == r('''<?print "\\u20ac"?>''')
	for c in "\x00\x80\u0100\u3042\n\r\t\f\b\a\"":
		assert c == r('<?print obj?>', obj=c) # This tests :func:`misc.javaexpr` for Java and :func:`ul4c._asjson` for JS

	# Test literal control characters (but '\r' and '\n' are not allowed)
	assert 'gu\trk' == r("<?print 'gu\trk'?>")
	assert 'gu\t\\rk' == r(r"<?print 'gu\t\\rk'?>")

	# Test triple quoted strings
	assert 'gu\r\nrk' == r("<?print '''gu\r\nrk'''?>")
	assert 'gu\r\nrk' == r('<?print """gu\r\nrk"""?>')

	assert 'no' == r('<?if ""?>yes<?else?>no<?end if?>')
	assert 'yes' == r('<?if "foo"?>yes<?else?>no<?end if?>')


@pytest.mark.ul4
def test_date(r):
	assert '2000-02-29' == r('<?print @(2000-02-29).isoformat()?>')
	assert '2000-02-29' == r('<?print @(2000-02-29T).isoformat()?>')
	assert '2000-02-29T12:34:00' == r('<?print @(2000-02-29T12:34).isoformat()?>')
	assert '2000-02-29T12:34:56' == r('<?print @(2000-02-29T12:34:56).isoformat()?>')
	if r is not render_php:
		assert '2000-02-29T12:34:56.987000' == r('<?print @(2000-02-29T12:34:56.987000).isoformat()?>') # JS and Java only supports milliseconds
	assert 'yes' == r('<?if @(2000-02-29T12:34:56.987654)?>yes<?else?>no<?end if?>')


@pytest.mark.ul4
def test_color(r):
	assert '255,255,255,255' == r('<?code c = #fff?><?print c[0]?>,<?print c[1]?>,<?print c[2]?>,<?print c[3]?>')
	assert '255,255,255,255' == r('<?code c = #ffffff?><?print c[0]?>,<?print c[1]?>,<?print c[2]?>,<?print c[3]?>')
	assert '18,52,86,255' == r('<?code c = #123456?><?print c[0]?>,<?print c[1]?>,<?print c[2]?>,<?print c[3]?>')
	assert '17,34,51,68' == r('<?code c = #1234?><?print c[0]?>,<?print c[1]?>,<?print c[2]?>,<?print c[3]?>')
	assert '18,52,86,120' == r('<?code c = #12345678?><?print c[0]?>,<?print c[1]?>,<?print c[2]?>,<?print c[3]?>')
	assert 'yes' == r('<?if #fff?>yes<?else?>no<?end if?>')


@pytest.mark.ul4
def test_list(r):
	assert '' == r('<?for item in []?><?print item?>;<?end for?>')
	assert '1;' == r('<?for item in [1]?><?print item?>;<?end for?>')
	assert '1;' == r('<?for item in [1,]?><?print item?>;<?end for?>')
	assert '1;2;' == r('<?for item in [1, 2]?><?print item?>;<?end for?>')
	assert '1;2;' == r('<?for item in [1, 2,]?><?print item?>;<?end for?>')
	assert 'no' == r('<?if []?>yes<?else?>no<?end if?>')
	assert 'yes' == r('<?if [1]?>yes<?else?>no<?end if?>')


@pytest.mark.ul4
def test_listcomp(r):
	assert "[2, 6]" == r("<?code d = [2*i for i in range(4) if i%2]?><?print d?>")
	assert "[0, 2, 4, 6]" == r("<?code d = [2*i for i in range(4)]?><?print d?>")

	# Make sure that the loop variables doesn't leak into the surrounding scope
	assert "undefined" == r("<?code d = [2*i for i in range(4)]?><?print type(i)?>")


@pytest.mark.ul4
def test_genexpr(r):
	assert "2, 6:" == r("<?code ge = (str(2*i) for i in range(4) if i%2)?><?print ', '.join(ge)?>:<?print ', '.join(ge)?>")
	assert "2, 6" == r("<?print ', '.join(str(2*i) for i in range(4) if i%2)?>")
	assert "0, 2, 4, 6" == r("<?print ', '.join(str(2*i) for i in range(4))?>")
	assert "0, 2, 4, 6" == r("<?print ', '.join((str(2*i) for i in range(4)))?>")
	assert "0:g; 1:r; 2:k" == r("<?for (i, c2) in enumerate(c for c in 'gurk' if c != 'u')?><?if i?>; <?end if?><?print i?>:<?print c2?><?end for?>")

	# Make sure that the loop variables doesn't leak into the surrounding scope
	assert "undefined" == r("<?code d = (2*i for i in range(4))?><?print type(i)?>")


@pytest.mark.ul4
def test_dict(r):
	assert '' == r('<?for (key, value) in {}.items()?><?print key?>:<?print value?>\n<?end for?>')
	assert '1:2\n' == r('<?for (key, value) in {1:2}.items()?><?print key?>:<?print value?>\n<?end for?>')
	assert '1:#fff\n' == r('<?for (key, value) in {1:#fff}.items()?><?print key?>:<?print value?>\n<?end for?>')
	assert '1:2\n' == r('<?for (key, value) in {1:2,}.items()?><?print key?>:<?print value?>\n<?end for?>')
	# With duplicate keys, later ones simply overwrite earlier ones
	assert '1:3\n' == r('<?for (key, value) in {1:2, 1: 3}.items()?><?print key?>:<?print value?>\n<?end for?>')
	assert 'no' == r('<?if {}?>yes<?else?>no<?end if?>')
	assert 'yes' == r('<?if {1:2}?>yes<?else?>no<?end if?>')

	# Make sure that the loop variables doesn't leak into the surrounding scope
	assert "undefined" == r("<?code d = {i: 2*i for i in range(4)}?><?print type(i)?>")


@pytest.mark.ul4
def test_dictcomp(r):
	# JS only supports string keys
	assert "" == r("<?code d = {str(i):2*i for i in range(10) if i%2}?><?if '2' in d?><?print d['2']?><?end if?>")
	assert "6" == r("<?code d = {str(i):2*i for i in range(10) if i%2}?><?if '3' in d?><?print d['3']?><?end if?>")
	assert "6" == r("<?code d = {str(i):2*i for i in range(10)}?><?print d['3']?>")


@pytest.mark.ul4
def test_print(r):
	assert "" == r("<?print None?>")
	assert "<foo>" == r("<?print '<foo>'?>")


@pytest.mark.ul4
def test_printx(r):
	assert "" == r("<?printx None?>")
	assert "&lt;foo&gt;" == r("<?printx '<foo>'?>")


@pytest.mark.ul4
def test_setvar(r):
	assert '42' == r('<?code x = 42?><?print x?>')
	assert 'xyzzy' == r('<?code x = "xyzzy"?><?print x?>')
	assert 'x,y' == r('<?code (x, y) = "xy"?><?print x?>,<?print y?>')
	assert '42' == r('<?code (x,) = [42]?><?print x?>')
	assert '17,23' == r('<?code (x,y) = [17, 23]?><?print x?>,<?print y?>')
	assert '17,23,37,42,105' == r('<?code ((v, w), (x,), (y,), z) = [[17, 23], [37], [42], 105]?><?print v?>,<?print w?>,<?print x?>,<?print y?>,<?print z?>')


@pytest.mark.ul4
def test_setvar_iterator(r):
	assert 'g;k' == r("<?code (x,y) = (c for c in 'gurk' if c < 'r')?><?print x?>;<?print y?>")


@pytest.mark.ul4
def test_addvar(r):
	for x in (17, 17., False, True):
		for y in (23, 23., False, True):
			assert x + y == eval(r('<?code x = {}?><?code x += {}?><?print x?>'.format(x, y)))
	assert 'xyzzy' == r('<?code x = "xyz"?><?code x += "zy"?><?print x?>')
	assert '[1, 2, 3, 4]' == r('<?code x = [1, 2]?><?code x += [3, 4]?><?print x?>')


@pytest.mark.ul4
def test_subvar(r):
	for x in (17, 17., False, True):
		for y in (23, 23., False, True):
			assert x - y == eval(r('<?code x = {}?><?code x -= {}?><?print x?>'.format(x, y)))


@pytest.mark.ul4
def test_mulvar(r):
	for x in (17, 17., False, True):
		for y in (23, 23., False, True):
			assert x * y == eval(r('<?code x = {}?><?code x *= {}?><?print x?>'.format(x, y)))
	for x in (17, False, True):
		y = "xyzzy"
		assert x * y == r('<?code x = {}?><?code x *= {!r}?><?print x?>'.format(x, y))
	assert 17*"xyzzy" == r('<?code x = "xyzzy"?><?code x *= 17?><?print x?>')


@pytest.mark.ul4
def test_floordivvar(r):
	for x in (5, -5, 5.0, -5.0, 4, -4, 4.0, -4.0, False, True):
		for y in (2, -2, 2.0, -2.0, True):
			assert x // y == eval(r('<?code x = {}?><?code x //= {}?><?print x?>'.format(x, y)))


@pytest.mark.ul4
def test_truedivvar(r):
	for x in (5, -5, 5.0, -5.0, 4, -4, 4.0, -4.0, False, True):
		for y in (2, -2, 2.0, -2.0, True):
			assert x / y == eval(r('<?code x = {}?><?code x /= {}?><?print x?>'.format(x, y)))


@pytest.mark.ul4
def test_modvar(r):
	for x in (1729, 1729.0, -1729, -1729.0, False, True):
		for y in (23, 23., -23, -23.0, True):
			assert x % y == eval(r('<?code x = {}?><?code x %= {}?><?print x?>'.format(x, y)))


@pytest.mark.ul4
def test_shiftleftvar(r):
	code = "<?code x <<= y?><?print x?>"

	assert "1" == r(code, x=True, y=False)
	assert "2" == r(code, x=True, y=True)
	assert "0" == r(code, x=1, y=-1)
	assert "-256" == r(code, x=-1, y=8)
	assert "2147483648" == r(code, x=1, y=31)
	assert "4294967296" == r(code, x=1, y=32)
	if r is render_js:
		# Javascript numbers don't have enough precision
		assert "18014398509481984" == r(code, x=1, y=54)
	else:
		assert "9223372036854775808" == r(code, x=1, y=63)
		assert "18446744073709551616" == r(code, x=1, y=64)
		assert "340282366920938463463374607431768211456" == r(code, x=1, y=128)


@pytest.mark.ul4
def test_shiftrightvar(r):
	code = "<?code x >>= y?><?print x?>"

	assert "1" == r(code, x=True, y=False)
	assert "0" == r(code, x=True, y=True)
	assert "2" == r(code, x=1, y=-1)
	assert "2147483648" == r(code, x=1, y=-31)
	assert "1" == r(code, x=2147483648, y=31)
	assert "0" == r(code, x=1, y=32)
	assert "-1" == r(code, x=-1, y=10)
	assert "-1" == r(code, x=-4, y=10)


@pytest.mark.ul4
def test_bitandvar(r):
	code = "<?code x &= y?><?print x?>"

	assert "0" == r(code, x=False, y=False)
	assert "0" == r(code, x=False, y=True)
	assert "1" == r(code, x=True, y=True)
	assert "1" == r(code, x=3, y=True)
	assert "12" == r(code, x=15, y=60)
	assert "0" == r(code, x=255, y=256)
	assert "0" == r(code, x=255, y=-256)
	assert "1" == r(code, x=255, y=-255)


@pytest.mark.ul4
def test_bitxorvar(r):
	code = "<?code x ^= y?><?print x?>"

	assert "0" == r(code, x=False, y=False)
	assert "1" == r(code, x=False, y=True)
	assert "0" == r(code, x=True, y=True)
	assert "2" == r(code, x=3, y=True)
	assert "51" == r(code, x=15, y=60)
	assert "511" == r(code, x=255, y=256)
	assert "-1" == r(code, x=255, y=-256)
	assert "-2" == r(code, x=255, y=-255)


@pytest.mark.ul4
def test_bitorvar(r):
	code = "<?code x |= y?><?print x?>"

	assert "0" == r(code, x=False, y=False)
	assert "1" == r(code, x=False, y=True)
	assert "1" == r(code, x=True, y=True)
	assert "3" == r(code, x=3, y=True)
	assert "63" == r(code, x=15, y=60)
	assert "511" == r(code, x=255, y=256)
	assert "-1" == r(code, x=255, y=-256)
	assert "-1" == r(code, x=255, y=-255)


@pytest.mark.ul4
def test_for_string(r):
	assert '' == r('<?for c in data?>(<?print c?>)<?end for?>', data="")
	assert '(g)(u)(r)(k)' == r('<?for c in data?>(<?print c?>)<?end for?>', data="gurk")


@pytest.mark.ul4
def test_for_list(r):
	assert '' == r('<?for c in data?>(<?print c?>)<?end for?>', data="")
	assert '(g)(u)(r)(k)' == r('<?for c in data?>(<?print c?>)<?end for?>', data=["g", "u", "r", "k"])


@pytest.mark.ul4
def test_for_dict(r):
	assert '' == r('<?for c in data?>(<?print c?>)<?end for?>', data={})
	assert '(a)(b)(c)' == r('<?for c in sorted(data)?>(<?print c?>)<?end for?>', data=dict(a=1, b=2, c=3))


@pytest.mark.ul4
def test_for_nested_loop(r):
	assert '[(1)(2)][(3)(4)]' == r('<?for list in data?>[<?for n in list?>(<?print n?>)<?end for?>]<?end for?>', data=[[1, 2], [3, 4]])


@pytest.mark.ul4
def test_for_leak(r):
	# Both loop variables and variables assigned in the block leak into the surrounding scope.
	assert '4;4' == r('<?code x = 17?><?code y = 23?><?for x in range(5)?><?code y = x?><?end for?><?print x?>;<?print y?>')


@pytest.mark.ul4
def test_for_unpacking(r):
	data = [
		("spam", "eggs", 17),
		("gurk", "hurz", 23),
		("hinz", "kunz", 42),
	]

	assert '(spam)(gurk)(hinz)' == r('<?for (a,) in data?>(<?print a?>)<?end for?>', data=[item[:1] for item in data])
	assert '(spam,eggs)(gurk,hurz)(hinz,kunz)' == r('<?for (a, b) in data?>(<?print a?>,<?print b?>)<?end for?>', data=[item[:2] for item in data])
	assert '(spam,eggs,17)(gurk,hurz,23)(hinz,kunz,42)' == r('<?for (a, b, c) in data?>(<?print a?>,<?print b?>,<?print c?>)<?end for?>', data=data)


@pytest.mark.ul4
def test_for_nested_unpacking(r):
	data = [
		(("spam", "eggs"), (17,), None),
		(("gurk", "hurz"), (23,), False),
		(("hinz", "kunz"), (42,), True),
	]

	assert '(spam,eggs,17,)(gurk,hurz,23,False)(hinz,kunz,42,True)' == r('<?for ((a, b), (c,), d) in data?>(<?print a?>,<?print b?>,<?print c?>,<?print d?>)<?end for?>', data=data)


@pytest.mark.ul4
def test_while(r):
	assert "0;1;2;" == r("<?code i = 0?><?while i < 3?><?print i?>;<?code i+=1?><?end while?>")


@pytest.mark.ul4
def test_while_break(r):
	assert "0;1;2;" == r("<?code i = 0?><?while i < 30?><?print i?>;<?code i+=1?><?if i == 3?><?break?><?end if?><?end while?>")


@pytest.mark.ul4
def test_break(r):
	assert '1, 2, ' == r('<?for i in [1,2,3]?><?print i?>, <?if i==2?><?break?><?end if?><?end for?>')


@pytest.mark.ul4
def test_break_nested(r):
	assert '1, 1, 2, 1, 2, 3, ' == r('<?for i in [1,2,3,4]?><?for j in [1,2,3,4]?><?print j?>, <?if j>=i?><?break?><?end if?><?end for?><?if i>=3?><?break?><?end if?><?end for?>')


@pytest.mark.ul4
def test_continue(r):
	assert '1, 3, ' == r('<?for i in [1,2,3]?><?if i==2?><?continue?><?end if?><?print i?>, <?end for?>')


@pytest.mark.ul4
def test_continue_nested(r):
	assert '1, 3, \n1, 3, \n' == r('<?for i in [1,2,3]?><?if i==2?><?continue?><?end if?><?for j in [1,2,3]?><?if j==2?><?continue?><?end if?><?print j?>, <?end for?>\n<?end for?>')


@pytest.mark.ul4
def test_if(r):
	assert '42' == r('<?if data?><?print data?><?end if?>', data=42)


@pytest.mark.ul4
def test_else(r):
	assert '42' == r('<?if data?><?print data?><?else?>no<?end if?>', data=42)
	assert 'no' == r('<?if data?><?print data?><?else?>no<?end if?>', data=0)


@pytest.mark.ul4
def test_block_errors(r):
	with raises("block unclosed"):
		r('<?for x in data?>')
	with raises("for ended by endif|endif doesn't match any if"):
		r('<?for x in data?><?end if?>')
	with raises("not in any block"):
		r('<?end?>')
	with raises("not in any block"):
		r('<?end for?>')
	with raises("not in any block"):
		r('<?end if?>')
	with raises("else doesn't match any if"):
		r('<?else?>')
	with raises("block unclosed"):
		r('<?if data?>')
	with raises("block unclosed"):
		r('<?if data?><?else?>')
	with raises("duplicate else in if/elif/else chain|else already seen in if"):
		r('<?if data?><?else?><?else?>')
	with raises("elif can't follow else in if/elif/else chain|else already seen in if"):
		r('<?if data?><?else?><?elif data?>')
	with raises("elif can't follow else in if/elif/else chain|else already seen in if"):
		r('<?if data?><?elif data?><?elif data?><?else?><?elif data?>')


@pytest.mark.ul4
def test_empty():
	with raises("expression required"):
		render_python('<?print?>')
	with raises("expression required"):
		render_python('<?if?>')
	with raises("expression required"):
		render_python('<<?if x?><?elif?><?end if?>')
	with raises("loop expression required"):
		render_python('<?for?>')
	with raises("statement required"):
		render_python('<?code?>')


@pytest.mark.ul4
def test_add(r):
	code = '<?print x + y?>'
	values = (17, 23, 1., -1.)

	for x in values:
		for y in values:
			assert x + y == eval(r(code, x=x, y=y)) # Using ``evaleq`` avoids problem with the nonexistant int/float distinction in JS
	assert 'foobar' == r('<?code x="foo"?><?code y="bar"?><?print x+y?>')
	assert '[1, 2, 3, 4]' == r('<?print x+y?>', x=[1, 2], y=[3, 4])
	assert '(f)(o)(o)(b)(a)(r)' == r('<?for i in data.foo+data.bar?>(<?print i?>)<?end for?>', data=dict(foo="foo", bar="bar"))
	assert "2012-10-18 00:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(1))
	assert "2013-10-17 00:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(365))
	assert "2012-10-17 12:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 12*60*60))
	assert "2012-10-17 00:00:01" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 1))
	if r is not render_php:
		assert "2012-10-17 00:00:00.500000" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 0, 500000))
		assert "2012-10-17 00:00:00.001000" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 0, 1000))
	assert "2 days, 0:00:00" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(1))
	assert "1 day, 0:00:01" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0, 1))
	assert "1 day, 0:00:00.000001" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0, 0, 1))
	assert "2 months" == r(code, x=misc.monthdelta(1), y=misc.monthdelta(1))
	assert "2000-02-01 00:00:00" == r(code, x=datetime.datetime(2000, 1, 1), y=misc.monthdelta(1))
	assert "1999-11-30 00:00:00" == r(code, x=datetime.datetime(2000, 1, 31), y=misc.monthdelta(-2))
	assert "2000-03-29 00:00:00" == r(code, x=datetime.datetime(2000, 2, 29), y=misc.monthdelta(1))
	assert "2001-02-28 00:00:00" == r(code, x=datetime.datetime(2000, 2, 29), y=misc.monthdelta(12))
	assert "2001-02-28 00:00:00" == r(code, x=misc.monthdelta(12), y=datetime.datetime(2000, 2, 29))


@pytest.mark.ul4
def test_sub(r):
	code = '<?print x - y?>'
	values = (17, 23, 1., -1.)

	for x in values:
		for y in values:
			assert x - y == eval(r(code, x=x, y=y))

	assert "2012-10-16 00:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(1))
	assert "2011-10-17 00:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(366))
	assert "2012-10-16 12:00:00" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 12*60*60))
	assert "2012-10-16 23:59:59" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 1))
	if r is not render_php:
		assert "2012-10-16 23:59:59.500000" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 0, 500000))
		assert "2012-10-16 23:59:59.999000" == r(code, x=datetime.datetime(2012, 10, 17), y=datetime.timedelta(0, 0, 1000))
	assert "0:00:00" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(1))
	assert "1 day, 0:00:00" == r(code, x=datetime.timedelta(2), y=datetime.timedelta(1))
	assert "23:59:59" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0, 1))
	assert "23:59:59.999999" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0, 0, 1))
	assert "-1 day, 23:59:59" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 1))
	assert "-1 day, 23:59:59.999999" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 0, 1))
	assert "2000-01-01 00:00:00" == r(code, x=datetime.datetime(2000, 2, 1), y=misc.monthdelta(1))
	assert "2000-02-29 00:00:00" == r(code, x=datetime.datetime(1999, 12, 31), y=misc.monthdelta(-2))
	assert "2000-02-29 00:00:00" == r(code, x=datetime.datetime(2000, 3, 29), y=misc.monthdelta(1))
	assert "1999-02-28 00:00:00" == r(code, x=datetime.datetime(2000, 2, 29), y=misc.monthdelta(12))
	assert "-1 month" == r(code, x=misc.monthdelta(2), y=misc.monthdelta(3))


@pytest.mark.ul4
def test_neg(r):
	code = "<?print -x?>"

	assert "0" == r(code, x=False)
	assert "-1" == r(code, x=True)
	assert "-17" == r(code, x=17)
	assert "-42.5" == r(code, x=42.5)
	assert "0:00:00" == r(code, x=datetime.timedelta())
	assert "-1 day, 0:00:00" == r(code, x=datetime.timedelta(1))
	assert "-1 day, 23:59:59" == r(code, x=datetime.timedelta(0, 1))
	assert "-1 day, 23:59:59.999999" == r(code, x=datetime.timedelta(0, 0, 1))
	assert "0 months" == r(code, x=misc.monthdelta())
	assert "-1 month" == r(code, x=misc.monthdelta(1))
	# This checks constant folding
	assert "0" == r("<?print -False?>")
	assert "-1" == r("<?print -True?>")
	assert "-2" == r("<?print -2?>")
	assert "-2.5" == r("<?print -2.5?>")


@pytest.mark.ul4
def test_bitnot(r):
	code = "<?print ~x?>"

	assert "-1" == r(code, x=False)
	assert "-2" == r(code, x=True)
	assert "-1" == r(code, x=0)
	assert "-256" == r(code, x=255)
	assert "-4294967297" == r(code, x=1 << 32)
	if r is render_js:
		# Javascript numbers don't have enough precision
		assert "-4503599627370497" == r(code, x=1 << 52)
	else:
		assert "-18446744073709551617" == r(code, x=1 << 64)


@pytest.mark.ul4
def test_mul(r):
	code = '<?print x * y?>'
	values = (17, 23, 1., -1.)

	for x in values:
		for y in values:
			assert x * y == eval(r(code, x=x, y=y))
	assert 17*"foo" == r('<?print 17*"foo"?>')
	assert 17*"foo" == r('<?code x=17?><?code y="foo"?><?print x*y?>')
	assert "foo"*17 == r('<?code x="foo"?><?code y=17?><?print x*y?>')
	assert "foo"*17 == r('<?print "foo"*17?>')
	assert "(foo)(bar)(foo)(bar)(foo)(bar)" == r('<?for i in 3*data?>(<?print i?>)<?end for?>', data=["foo", "bar"])
	assert "0:00:00" == r(code, x=4, y=datetime.timedelta())
	assert "4 days, 0:00:00" == r(code, x=4, y=datetime.timedelta(1))
	assert "2 days, 0:00:00" == r(code, x=4, y=datetime.timedelta(0, 12*60*60))
	assert "0:00:02" == r(code, x=4, y=datetime.timedelta(0, 0, 500000))
	assert "12:00:00" == r(code, x=0.5, y=datetime.timedelta(1))
	assert "0:00:00" == r(code, x=datetime.timedelta(), y=4)
	assert "4 days, 0:00:00" == r(code, x=datetime.timedelta(1), y=4)
	assert "2 days, 0:00:00" == r(code, x=datetime.timedelta(0, 12*60*60), y=4)
	assert "0:00:02" == r(code, x=datetime.timedelta(0, 0, 500000), y=4)
	assert "12:00:00" == r(code, x=datetime.timedelta(1), y=0.5)
	assert "4 months" == r(code, x=4, y=misc.monthdelta(1))
	assert "4 months" == r(code, x=misc.monthdelta(1), y=4)


@pytest.mark.ul4
def test_truediv(r):
	code = "<?print x / y?>"

	assert "0.5" == r('<?print 1/2?>')
	assert "0.5" == r('<?code x=1?><?code y=2?><?print x/y?>')
	assert "0:00:00" == r(code, x=datetime.timedelta(), y=4)
	assert "2 days, 0:00:00" == r(code, x=datetime.timedelta(8), y=4)
	assert "12:00:00" == r(code, x=datetime.timedelta(4), y=8)
	assert "0:00:00.500000" == r(code, x=datetime.timedelta(0, 4), y=8)
	assert "2 days, 0:00:00" == r(code, x=datetime.timedelta(1), y=0.5)
	assert "9:36:00" == r(code, x=datetime.timedelta(1), y=2.5)
	assert "0:00:00" == r(code, x=datetime.timedelta(), y=4)
	assert "2 days, 0:00:00" == r(code, x=datetime.timedelta(8), y=4)
	assert "12:00:00" == r(code, x=datetime.timedelta(4), y=8)
	assert "0:00:00.500000" == r(code, x=datetime.timedelta(0, 4), y=8)
	assert 2.0 == eval(r(code, x=datetime.timedelta(4), y=datetime.timedelta(2)))
	assert 2.0 == eval(r(code, x=misc.monthdelta(4), y=misc.monthdelta(2)))


@pytest.mark.ul4
def test_floordiv(r):
	assert "0" == r('<?print 1//2?>')
	assert "0" == r('<?code x=1?><?code y=2?><?print x//y?>')
	assert "1 month" == r('<?print x//y?>', x=misc.monthdelta(3), y=2)


@pytest.mark.ul4
def test_mod(r):
	values = (17, 23, 17., 23.)

	for x in values:
		for y in values:
			assert x % y == eval(r('<?print {} % {}?>'.format(x, y)))
			assert x % y == eval(r('<?print x % y?>', x=x, y=y))


@pytest.mark.ul4
def test_shiftleft(r):
	code = "<?print x << y?>"

	assert "16" == r("<?print 1 << 4?>")
	assert "2" == r("<?print True << True?>")
	assert "1" == r(code, x=True, y=False)
	assert "2" == r(code, x=True, y=True)
	assert "0" == r(code, x=1, y=-1)
	assert "-256" == r(code, x=-1, y=8)
	assert "2147483648" == r(code, x=1, y=31)
	assert "4294967296" == r(code, x=1, y=32)
	if r is render_js:
		# Javascript numbers don't have enough precision
		assert "9007199254740992" == r(code, x=1, y=53)
	else:
		assert "9223372036854775808" == r(code, x=1, y=63)
		assert "18446744073709551616" == r(code, x=1, y=64)
		assert "340282366920938463463374607431768211456" == r(code, x=1, y=128)


@pytest.mark.ul4
def test_shiftright(r):
	code = "<?print x >> y?>"

	assert "1" == r("<?print 16 >> 4?>")
	assert "0" == r("<?print True >> True?>")
	assert "1" == r(code, x=True, y=False)
	assert "0" == r(code, x=True, y=True)
	assert "2" == r(code, x=1, y=-1)
	assert "2147483648" == r(code, x=1, y=-31)
	assert "1" == r(code, x=2147483648, y=31)
	assert "0" == r(code, x=1, y=32)
	assert "-1" == r(code, x=-1, y=10)
	assert "-1" == r(code, x=-4, y=10)


@pytest.mark.ul4
def test_bitand(r):
	code = "<?print x & y?>"

	assert "2" == r("<?print 3 & 6?>")
	assert "1" == r("<?print True & True?>")
	assert "0" == r(code, x=False, y=False)
	assert "0" == r(code, x=False, y=True)
	assert "1" == r(code, x=True, y=True)
	assert "1" == r(code, x=3, y=True)
	assert "12" == r(code, x=15, y=60)
	assert "0" == r(code, x=255, y=256)
	assert "0" == r(code, x=255, y=-256)
	assert "1" == r(code, x=255, y=-255)


@pytest.mark.ul4
def test_bitxor(r):
	code = "<?print x ^ y?>"

	assert "5" == r("<?print 3 ^ 6?>")
	assert "0" == r("<?print True ^ True?>")
	assert "0" == r(code, x=False, y=False)
	assert "1" == r(code, x=False, y=True)
	assert "0" == r(code, x=True, y=True)
	assert "2" == r(code, x=3, y=True)
	assert "51" == r(code, x=15, y=60)
	assert "511" == r(code, x=255, y=256)
	assert "-1" == r(code, x=255, y=-256)
	assert "-2" == r(code, x=255, y=-255)


@pytest.mark.ul4
def test_bitor(r):
	code = "<?print x | y?>"

	assert "7" == r("<?print 3 | 6?>")
	assert "1" == r("<?print False | True?>")
	assert "0" == r(code, x=False, y=False)
	assert "1" == r(code, x=False, y=True)
	assert "1" == r(code, x=True, y=True)
	assert "3" == r(code, x=3, y=True)
	assert "63" == r(code, x=15, y=60)
	assert "511" == r(code, x=255, y=256)
	assert "-1" == r(code, x=255, y=-256)
	assert "-1" == r(code, x=255, y=-255)


@pytest.mark.ul4
def test_eq(r):
	code = '<?print x == y?>'
	numbervalues = (17, 23, 17., 23.)

	for x in numbervalues:
		for y in numbervalues:
			assert str(x == y) == r('<?print {} == {}?>'.format(x, y))
			assert str(x == y) == r(code, x=x, y=y)

	assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0))
	assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(1))
	assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 1))
	assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 0, 1))
	assert "True" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(0))
	assert "False" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(1))


@pytest.mark.ul4
def test_ne(r):
	code = '<?print x != y?>'
	values = (17, 23, 17., 23.)

	for x in values:
		for y in values:
			assert str(x != y) == r('<?print {} != {}?>'.format(x, y))
			assert str(x != y) == r(code, x=x, y=y)

	assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0))
	assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(1))
	assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 1))
	assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 0, 1))
	assert "False" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(0))
	assert "True" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(1))


@pytest.mark.ul4
def test_lt(r):
	code = '<?print x < y?>'
	values = (17, 23, 17., 23.)

	for x in values:
		for y in values:
			assert str(x < y) == r('<?print {} < {}?>'.format(x, y))
			assert str(x < y) == r(code, x=x, y=y)

	assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0))
	assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(1))
	assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 1))
	assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 0, 1))
	assert "False" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(0))
	assert "True" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(1))


@pytest.mark.ul4
def test_le(r):
	code = '<?print x <= y?>'
	values = (17, 23, 17., 23.)

	for x in values:
		for y in values:
			assert str(x <= y) == r('<?print {} <= {}?>'.format(x, y))
			assert str(x <= y) == r(code, x=x, y=y)

	assert "True" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(1))
	assert "False" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0))
	assert "False" == r(code, x=datetime.timedelta(0, 1), y=datetime.timedelta(0))
	assert "False" == r(code, x=datetime.timedelta(0, 0, 1), y=datetime.timedelta(0))
	assert "True" == r(code, x=misc.monthdelta(1), y=misc.monthdelta(1))
	assert "False" == r(code, x=misc.monthdelta(1), y=misc.monthdelta(0))


@pytest.mark.ul4
def test_gt(r):
	code = '<?print x > y?>'
	values = (17, 23, 17., 23.)

	for x in values:
		for y in values:
			assert str(x > y) == r('<?print {} > {}?>'.format(x, y))
			assert str(x > y) == r(code, x=x, y=y)

	assert "False" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(1))
	assert "True" == r(code, x=datetime.timedelta(1), y=datetime.timedelta(0))
	assert "True" == r(code, x=datetime.timedelta(0, 1), y=datetime.timedelta(0))
	assert "True" == r(code, x=datetime.timedelta(0, 0, 1), y=datetime.timedelta(0))
	assert "False" == r(code, x=misc.monthdelta(1), y=misc.monthdelta(1))
	assert "True" == r(code, x=misc.monthdelta(1), y=misc.monthdelta(0))


@pytest.mark.ul4
def test_ge(r):
	code = '<?print x >= y?>'
	values = (17, 23, 17., 23.)

	for x in values:
		for y in values:
			assert str(x >= y) == r('<?print {} >= {}?>'.format(x, y))
			assert str(x >= y) == r(code, x=x, y=y)

	assert "True" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0))
	assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(1))
	assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 1))
	assert "False" == r(code, x=datetime.timedelta(0), y=datetime.timedelta(0, 0, 1))
	assert "True" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(0))
	assert "False" == r(code, x=misc.monthdelta(0), y=misc.monthdelta(1))


@pytest.mark.ul4
def test_contains(r):
	code = '<?print x in y?>'

	assert "True" == r(code, x=2, y=[1, 2, 3])
	assert "False" == r(code, x=4, y=[1, 2, 3])
	assert "True" == r(code, x="ur", y="gurk")
	assert "False" == r(code, x="un", y="gurk")
	assert "True" == r(code, x="a", y={"a": 1, "b": 2})
	assert "False" == r(code, x="c", y={"a": 1, "b": 2})
	assert "True" == r(code, x=0xff, y=color.Color(0x00, 0x80, 0xff, 0x42))
	assert "False" == r(code, x=0x23, y=color.Color(0x00, 0x80, 0xff, 0x42))


@pytest.mark.ul4
def test_notcontains(r):
	code = '<?print x not in y?>'

	assert "False" == r(code, x=2, y=[1, 2, 3])
	assert "True" == r(code, x=4, y=[1, 2, 3])
	assert "False" == r(code, x="ur", y="gurk")
	assert "True" == r(code, x="un", y="gurk")
	assert "False" == r(code, x="a", y={"a": 1, "b": 2})
	assert "True" == r(code, x="c", y={"a": 1, "b": 2})
	assert "False" == r(code, x=0xff, y=color.Color(0x00, 0x80, 0xff, 0x42))
	assert "True" == r(code, x=0x23, y=color.Color(0x00, 0x80, 0xff, 0x42))


@pytest.mark.ul4
def test_and(r):
	assert "False" == r('<?print x and y?>', x=False, y=False)
	assert "False" == r('<?print x and y?>', x=False, y=True)
	assert "0" == r('<?print x and y?>', x=0, y=True)


@pytest.mark.ul4
def test_or(r):
	assert "False" == r('<?print x or y?>', x=False, y=False)
	assert "True" == r('<?print x or y?>', x=False, y=True)
	assert "42" == r('<?print x or y?>', x=42, y=True)


@pytest.mark.ul4
def test_not(r):
	assert "True" == r('<?print not x?>', x=False)
	assert "False" == r('<?print not x?>', x=42)


@pytest.mark.ul4
def test_ifexpr(r):
	assert "17" == r('<?print x if y else z?>', x=17, y=True, z=23)
	assert "23" == r('<?print x if y else z?>', x=17, y=False, z=23)
	assert "17" == r('<?print 17 if True else 23?>')
	assert "23" == r('<?print 17 if False else 23?>')


@pytest.mark.ul4
def test_getitem(r):
	assert "u" == r("<?print 'gurk'[1]?>")
	assert "u" == r("<?print x[1]?>", x="gurk")
	assert "u" == r("<?print 'gurk'[-3]?>")
	assert "u" == r("<?print x[-3]?>", x="gurk")
	assert "" == r("<?print 'gurk'[4]?>")
	assert "" == r("<?print x[4]?>", x="gurk")
	assert "" == r("<?print 'gurk'[-5]?>")
	assert "" == r("<?print x[-5]?>", x="gurk")


@pytest.mark.ul4
def test_getslice(r):
	assert "ur" == r("<?print 'gurk'[1:3]?>")
	assert "ur" == r("<?print x[1:3]?>", x="gurk")
	assert "ur" == r("<?print 'gurk'[-3:-1]?>")
	assert "ur" == r("<?print x[-3:-1]?>", x="gurk")
	assert "" == r("<?print 'gurk'[4:10]?>")
	assert "" == r("<?print x[4:10]?>", x="gurk")
	assert "" == r("<?print 'gurk'[-10:-5]?>")
	assert "" == r("<?print x[-10:-5]?>", x="gurk")
	assert "urk" == r("<?print 'gurk'[1:]?>")
	assert "urk" == r("<?print x[1:]?>", x="gurk")
	assert "urk" == r("<?print 'gurk'[-3:]?>")
	assert "urk" == r("<?print x[-3:]?>", x="gurk")
	assert "" == r("<?print 'gurk'[4:]?>")
	assert "" == r("<?print x[4:]?>", x="gurk")
	assert "gurk" == r("<?print 'gurk'[-10:]?>")
	assert "gurk" == r("<?print x[-10:]?>", x="gurk")
	assert "gur" == r("<?print 'gurk'[:3]?>")
	assert "gur" == r("<?print x[:3]?>", x="gurk")
	assert "gur" == r("<?print 'gurk'[:-1]?>")
	assert "gur" == r("<?print x[:-1]?>", x="gurk")
	assert "gurk" == r("<?print 'gurk'[:10]?>")
	assert "gurk" == r("<?print x[:10]?>", x="gurk")
	assert "" == r("<?print 'gurk'[:-5]?>")
	assert "" == r("<?print x[:-5]?>", x="gurk")
	assert "05" == r("<?print ('0' + str(x))[-2:]?>", x=5)
	assert "15" == r("<?print ('0' + str(x))[-2:]?>", x=15)
	assert "gurk" == r("<?print 'gurk'[:]?>")
	assert "gurk" == r("<?print x[:]?>", x="gurk")
	assert "[1, 2]" == r("<?print x[:]?>", x=[1, 2])


@pytest.mark.ul4
def test_setslice(r):
	assert "[1, -2, -3, 4]" == r("<?code x = [1, 2, 3, 4]?><?code x[1:3] = [-2, -3]?><?print x?>")
	assert "[1, -1, -4, -9, 4]" == r("<?code x = [1, 2, 3, 4]?><?code x[1:-1] = (-i*i for i in range(1, 4))?><?print x?>")
	assert "[-1, -4, -9]" == r("<?code x = [1, 2, 3, 4]?><?code x[:] = (-i*i for i in range(1, 4))?><?print x?>")


@pytest.mark.ul4
def test_nested(r):
	sc = "4"
	sv = "x"
	n = 4
	# when using 8 Java will output "An irrecoverable stack overflow has occurred"
	depth = 7
	for i in range(depth):
		sc = "({})+({})".format(sc, sc)
		sv = "({})+({})".format(sv, sv)
		n = n + n

	assert str(n) == r('<?print {}?>'.format(sc))
	assert str(n) == r('<?code x=4?><?print {}?>'.format(sv))


@pytest.mark.ul4
def test_precedence(r):
	assert "14" == r('<?print 2+3*4?>')
	assert "20" == r('<?print (2+3)*4?>')
	assert "10" == r('<?print -2+-3*-4?>')
	assert "14" == r('<?print --2+--3*--4?>')
	assert "14" == r('<?print (-(-2))+(-((-3)*-(-4)))?>')
	assert "42" == r('<?print 2*data.value?>', data=dict(value=21))
	assert "42" == r('<?print data.value[0]?>', data=dict(value=[42]))
	assert "42" == r('<?print data[0].value?>', data=[dict(value=42)])
	assert "42" == r('<?print data[0][0][0]?>', data=[[[42]]])
	assert "42" == r('<?print data.value.value[0]?>', data=dict(value=dict(value=[42])))
	assert "42" == r('<?print data.value.value[0].value.value[0]?>', data=dict(value=dict(value=[dict(value=dict(value=[42]))])))

@pytest.mark.ul4
def test_associativity(r):
	assert "9" == r('<?print 2+3+4?>')
	assert "-5" == r('<?print 2-3-4?>')
	assert "24" == r('<?print 2*3*4?>')
	if r is not render_js:
		assert "2.0" == r('<?print 24/6/2?>')
		assert "2" == r('<?print 24//6//2?>')
	else:
		assert 2.0 == eval(r('<?print 24/6/2?>'))
		assert 2 == eval(r('<?print 24//6//2?>'))

@pytest.mark.ul4
def test_bracket(r):
	sc = "4"
	sv = "x"
	for i in range(10):
		sc = "({})".format(sc)
		sv = "({})".format(sv)

	assert "4" == r('<?print {}?>'.format(sc))
	assert "4" == r('<?code x=4?><?print {}?>'.format(sv))


@pytest.mark.ul4
def test_callfunc_args(r):
	assert "@(2013-01-07)" == r("<?print repr(date(2013, 1, 7))?>")
	assert "@(2013-01-07)" == r("<?print repr(date(2013, 1, day=7))?>")
	assert "@(2013-01-07)" == r("<?print repr(date(2013, month=1, day=7))?>")
	assert "@(2013-01-07)" == r("<?print repr(date(year=2013, month=1, day=7))?>")
	assert "@(2013-01-07)" == r("<?print repr(date(2013, *[1, 7]))?>")
	assert "@(2013-01-07)" == r("<?print repr(date(*[2013, 1, 7]))?>")
	assert "@(2013-01-07)" == r("<?print repr(date(year=2013, **{'month': 1, 'day': 7}))?>")
	assert "@(2013-01-07)" == r("<?print repr(date(2013, *[1], **{'day': 7}))?>")


@pytest.mark.ul4
def test_function_now(r):
	now = str(datetime.datetime.now())

	with raises(argumentmismatchmessage):
		r("<?print now(1)?>")
	with raises(argumentmismatchmessage):
		r("<?print now(1, 2)?>")
	with raises(argumentmismatchmessage):
		r("<?print now(foo=1)?>")
	assert now <= r("<?print now()?>")


@pytest.mark.ul4
def test_function_utcnow(r):
	utcnow = str(datetime.datetime.utcnow())

	with raises(argumentmismatchmessage):
		r("<?print utcnow(1)?>")
	with raises(argumentmismatchmessage):
		r("<?print utcnow(1, 2)?>")
	with raises(argumentmismatchmessage):
		r("<?print utcnow(foo=1)?>")
	# JS and Java only have milliseconds precision, but this shouldn't lead to problems here, as rendering the template takes longer than a millisecond
	assert utcnow <= r("<?print utcnow()?>")


@pytest.mark.ul4
def test_function_date(r):
	assert "@(2012-10-06)" == r("<?print repr(date(2012, 10, 6))?>")
	assert "@(2012-10-06T12:00:00)" == r("<?print repr(date(2012, 10, 6, 12))?>")
	assert "@(2012-10-06T12:34:00)" == r("<?print repr(date(2012, 10, 6, 12, 34))?>")
	assert "@(2012-10-06T12:34:56)" == r("<?print repr(date(2012, 10, 6, 12, 34, 56))?>")
	if r is not render_php:
		assert "@(2012-10-06T12:34:56.987000)" == r("<?print repr(date(2012, 10, 6, 12, 34, 56, 987000))?>")

	# Make sure that the parameters have the same name in all implementations
	assert "@(2012-10-06T12:34:56)" == r("<?print repr(date(year=2012, month=10, day=6, hour=12, minute=34, second=56, microsecond=0))?>")


@pytest.mark.ul4
def test_function_timedelta(r):
	with raises(argumentmismatchmessage):
		r("<?print timedelta(1, 2, 3, 4)?>")
	assert "1 day, 0:00:00" == r("<?print timedelta(1)?>")
	assert "-1 day, 0:00:00" == r("<?print timedelta(-1)?>")
	assert "2 days, 0:00:00" == r("<?print timedelta(2)?>")
	assert "0:00:01" == r("<?print timedelta(0, 0, 1000000)?>")
	assert "1 day, 0:00:00" == r("<?print timedelta(0, 0, 24*60*60*1000000)?>")
	assert "1 day, 0:00:00" == r("<?print timedelta(0, 24*60*60)?>")
	assert "12:00:00" == r("<?print timedelta(0.5)?>")
	assert "0:00:00.500000" == r("<?print timedelta(0, 0.5)?>")
	assert "0:00:00.500000" == r("<?print timedelta(0.5/(24*60*60))?>")
	assert "-1 day, 12:00:00" == r("<?print timedelta(-0.5)?>")
	assert "-1 day, 23:59:59.500000" == r("<?print timedelta(0, -0.5)?>")
	assert "0:00:01" == r("<?print timedelta(0, 1)?>")
	assert "0:01:00" == r("<?print timedelta(0, 60)?>")
	assert "1:00:00" == r("<?print timedelta(0, 60*60)?>")
	assert "1 day, 1:01:01.000001" == r("<?print timedelta(1, 60*60+60+1, 1)?>")
	assert "0:00:00.000001" == r("<?print timedelta(0, 0, 1)?>")
	assert "-1 day, 23:59:59" == r("<?print timedelta(0, -1)?>")
	assert "-1 day, 23:59:59.999999" == r("<?print timedelta(0, 0, -1)?>")

	# Make sure that the parameters have the same name in all implementations
	assert "0:00:00.000001" == r("<?print timedelta(days=0, seconds=0, microseconds=1)?>")


@pytest.mark.ul4
def test_function_monthdelta(r):
	with raises(argumentmismatchmessage):
		r("<?print monthdelta(1, 2)?>")
	assert "0 months" == r("<?print monthdelta()?>")
	assert "2 months" == r("<?print monthdelta(2)?>")
	assert "1 month" == r("<?print monthdelta(1)?>")
	assert "-1 month" == r("<?print monthdelta(-1)?>")

	# Make sure that the parameters have the same name in all implementations
	assert "1 month" == r("<?print monthdelta(months=1)?>")


@pytest.mark.ul4
def test_function_random(r):
	with raises(argumentmismatchmessage):
		r("<?print random(1)?>")
	with raises(argumentmismatchmessage):
		r("<?print random(1, 2)?>")
	with raises(argumentmismatchmessage):
		r("<?print random(foo=1)?>")
	assert "ok" == r("<?code r = random()?><?if r>=0 and r<1?>ok<?else?>fail<?end if?>")


@pytest.mark.ul4
def test_function_randrange(r):
	with raises(argumentmismatchmessage):
		r("<?print randrange()?>")
	with raises(argumentmismatchmessage):
		r("<?print randrange(foo=1)?>")
	assert "ok" == r("<?code r = randrange(4)?><?if r>=0 and r<4?>ok<?else?>fail<?end if?>")
	assert "ok" == r("<?code r = randrange(17, 23)?><?if r>=17 and r<23?>ok<?else?>fail<?end if?>")
	assert "ok" == r("<?code r = randrange(17, 23, 2)?><?if r>=17 and r<23 and r%2?>ok<?else?>fail<?end if?>")


@pytest.mark.ul4
def test_function_randchoice(r):
	with raises(argumentmismatchmessage):
		r("<?print randchoice()?>")
	assert "ok" == r("<?code r = randchoice('abc')?><?if r in 'abc'?>ok<?else?>fail<?end if?>")
	assert "ok" == r("<?code s = [17, 23, 42]?><?code r = randchoice(s)?><?if r in s?>ok<?else?>fail<?end if?>")
	assert "ok" == r("<?code s = #12345678?><?code sl = [0x12, 0x34, 0x56, 0x78]?><?code r = randchoice(s)?><?if r in sl?>ok<?else?>fail<?end if?>")

	# Make sure that the parameters have the same name in all implementations
	assert "ok" == r("<?code s = [17, 23, 42]?><?code r = randchoice(sequence=s)?><?if r in s?>ok<?else?>fail<?end if?>")


@pytest.mark.ul4
def test_function_xmlescape(r):
	with raises(argumentmismatchmessage):
		r("<?print xmlescape()?>")
	with raises(argumentmismatchmessage):
		r("<?print xmlescape(1, 2)?>")
	assert "&lt;&lt;&gt;&gt;&amp;&#39;&quot;gurk" == r("<?print xmlescape(data)?>", data='<<>>&\'"gurk')

	# Make sure that the parameters have the same name in all implementations
	assert "42" == r("<?print xmlescape(obj=data)?>", data=42)


@pytest.mark.ul4
def test_function_csv(r):
	with raises(argumentmismatchmessage):
		r("<?print csv()?>")
	with raises(argumentmismatchmessage):
		r("<?print csv(1, 2)?>")
	assert "" == r("<?print csv(data)?>", data=None)
	assert "False" == r("<?print csv(data)?>", data=False)
	assert "True" == r("<?print csv(data)?>", data=True)
	assert "42" == r("<?print csv(data)?>", data=42)
	# no check for float
	assert "abc" == r("<?print csv(data)?>", data="abc")
	assert '"a,b,c"' == r("<?print csv(data)?>", data="a,b,c")
	assert '"a""b""c"' == r("<?print csv(data)?>", data='a"b"c')
	assert '"a\nb\nc"' == r("<?print csv(data)?>", data="a\nb\nc")

	# Make sure that the parameters have the same name in all implementations
	assert "42" == r("<?print csv(obj=data)?>", data=42)


@pytest.mark.ul4
def test_function_asjson(r):
	with raises(argumentmismatchmessage):
		r("<?print asjson()?>")
	with raises(argumentmismatchmessage):
		r("<?print asjson(1, 2)?>")
	assert "null" == r("<?print asjson(data)?>", data=None)
	assert "false" == r("<?print asjson(data)?>", data=False)
	assert "true" == r("<?print asjson(data)?>", data=True)
	assert "42" == r("<?print asjson(data)?>", data=42)
	# no check for float
	assert '"abc"' == r("<?print asjson(data)?>", data="abc")
	assert '"\'"' == r("<?print asjson(data)?>", data="'")
	assert '"\\\""' == r("<?print asjson(data)?>", data='"')
	assert '[1, 2, 3]' == r("<?print asjson(data)?>", data=[1, 2, 3])
	assert '[1, 2, 3]' == r("<?print asjson(data)?>", data=PseudoList([1, 2, 3]))
	assert '{"one": 1}' == r("<?print asjson(data)?>", data={"one": 1})
	assert '{"one": 1}' == r("<?print asjson(data)?>", data=PseudoDict({"one": 1}))

	# Make sure that the parameters have the same name in all implementations
	assert "42" == r("<?print asjson(obj=data)?>", data=42)


@pytest.mark.ul4
def test_function_fromjson(r):
	code = "<?print repr(fromjson(data))?>"
	with raises(argumentmismatchmessage):
		r("<?print fromjson()?>")
	with raises(argumentmismatchmessage):
		r("<?print fromjson(1, 2)?>")
	assert "None" == r(code, data="null")
	assert "False" == r(code, data="false")
	assert "True" == r(code, data="true")
	assert "42" == r(code, data="42")
	# no check for float
	assert r(code, data='"abc"') in ('"abc"', "'abc'")
	assert '[1, 2, 3]' == r(code, data="[1, 2, 3]")
	assert r(code, data='{"one": 1}') in ('{"one": 1}', "{'one': 1}")

	# Make sure that the parameters have the same name in all implementations
	assert "42" == r("<?print fromjson(string=data)?>", data="42")


@pytest.mark.ul4
def test_function_ul4on(r):
	code = "<?print repr(fromul4on(asul4on(data)))?>"

	with raises(argumentmismatchmessage):
		r("<?print asul4on()?>")
	with raises(argumentmismatchmessage):
		r("<?print asul4on(1, 2)?>")
	with raises(argumentmismatchmessage):
		r("<?print fromul4on()?>")
	with raises(argumentmismatchmessage):
		r("<?print fromul4on(1, 2)?>")
	assert "None" == r(code, data=None)
	assert "False" == r(code, data=False)
	assert "True" == r(code, data=True)
	assert "42" == r(code, data=42)
	# no check for float
	assert r(code, data="abc") in ('"abc"', "'abc'")
	assert '[1, 2, 3]' == r(code, data=[1, 2, 3])
	assert r(code, data={'one': 1}) in ('{"one": 1}', "{'one': 1}")

	# Make sure that the parameters have the same name in all implementations
	assert "42" == r("<?print repr(fromul4on(string=asul4on(obj=data)))?>", data=42)


@pytest.mark.ul4
def test_function_str(r):
	code = "<?print str(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print str(1, 2)?>")
	assert "" == r("<?print str()?>")
	assert "" == r(code, data=None)
	assert "True" == r(code, data=True)
	assert "False" == r(code, data=False)
	assert "42" == r(code, data=42)
	assert "4.2" == r(code, data=4.2)
	assert "foo" == r(code, data="foo")
	assert "2011-02-09 00:00:00" == r(code, data=datetime.datetime(2011, 2, 9))
	assert "2011-02-09 12:34:56" == r(code, data=datetime.datetime(2011, 2, 9, 12, 34, 56))
	if r is not render_php:
		assert "2011-02-09 12:34:56.987000" == r(code, data=datetime.datetime(2011, 2, 9, 12, 34, 56, 987000))
	assert "0:00:00" == r(code, data=datetime.timedelta())
	assert "1 day, 0:00:00" == r(code, data=datetime.timedelta(1))
	assert "-1 day, 0:00:00" == r(code, data=datetime.timedelta(-1))
	assert "2 days, 0:00:00" == r(code, data=datetime.timedelta(2))
	assert "0:00:01" == r(code, data=datetime.timedelta(0, 1))
	assert "0:01:00" == r(code, data=datetime.timedelta(0, 60))
	assert "1:00:00" == r(code, data=datetime.timedelta(0, 60*60))
	assert "1 day, 1:01:01.000001" == r(code, data=datetime.timedelta(1, 60*60+60+1, 1))
	assert "0:00:00.000001" == r(code, data=datetime.timedelta(0, 0, 1))
	assert "-1 day, 23:59:59" == r(code, data=datetime.timedelta(0, -1))
	assert "-1 day, 23:59:59.999999" == r(code, data=datetime.timedelta(0, 0, -1))

	# Make sure that the parameters have the same name in all implementations
	assert "42" == r("<?print str(obj=data)?>", data=42)


@pytest.mark.ul4
def test_function_bool(r):
	with raises(argumentmismatchmessage):
		r("<?print bool(1, 2)?>")
	assert "False" == r("<?print bool()?>")
	code = "<?print bool(data)?>"
	assert "True" == r(code, data=True)
	assert "False" == r(code, data=False)
	assert "False" == r(code, data=0)
	assert "True" == r(code, data=42)
	assert "False" == r(code, data=0.0)
	assert "True" == r(code, data=42.5)
	assert "False" == r(code, data="")
	assert "True" == r(code, data="gurk")
	assert "False" == r(code, data=[])
	assert "True" == r(code, data=["gurk"])
	assert "False" == r(code, data={})
	assert "True" == r(code, data={"gurk": "hurz"})
	assert "True" == r(code, data=datetime.datetime.now())
	assert "False" == r(code, data=datetime.timedelta())
	assert "True" == r(code, data=datetime.timedelta(1))
	assert "False" == r(code, data=misc.monthdelta())
	assert "True" == r(code, data=misc.monthdelta(1))

	# Make sure that the parameters have the same name in all implementations
	assert "True" == r("<?print bool(obj=data)?>", data=42)


@pytest.mark.ul4
def test_function_list(r):
	with raises(argumentmismatchmessage):
		r("<?print list(1, 2)?>")
	assert "[]" == r("<?print list()?>")
	assert "[1, 2]" == r("<?print list(data)?>", data=[1, 2])
	assert "g" == r("<?print list(data)[0]?>", data="gurk")
	assert "foo42" == r("<?codex = list(data.items())?><?print x[0][0]?><?print x[0][1]?>", data={"foo": 42})
	assert "[0, 1, 2]" == r("<?print repr(list(range(3)))?>")

	# Make sure that the parameters have the same name in all implementations
	assert "g" == r("<?print list(iterable=data)[0]?>", data="gurk")


@pytest.mark.ul4
def test_function_int(r):
	with raises(argumentmismatchmessage):
		r("<?print int(1, 2, 3)?>")
	with raises("int\\(\\) argument must be a string or a number|int\\(null\\) not supported"):
		r("<?print int(data)?>", data=None)
	with raises("invalid literal for int|NumberFormatException"):
		r("<?print int(data)?>", data="foo")
	assert "0" == r("<?print int()?>")
	assert "1" == r("<?print int(data)?>", data=True)
	assert "0" == r("<?print int(data)?>", data=False)
	assert "42" == r("<?print int(data)?>", data=42)
	assert "4" == r("<?print int(data)?>", data=4.2)
	assert "42" == r("<?print int(data)?>", data="42")
	assert "66" == r("<?print int(data, 16)?>", data="42")

	# Make sure that the parameters have the same name in all implementations
	assert "42" == r("<?print int(obj=data, base=None)?>", data=42)


@pytest.mark.ul4
def test_function_float(r):
	code = "<?print float(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print float(1, 2, 3)?>")
	with raises("float\\(\\) argument must be a string or a number|float\\(null\\) not supported"):
		r(code, data=None)
	assert "4.2" == r(code, data=4.2)
	if r is not render_js:
		assert "0.0" == r("<?print float()?>")
		assert "1.0" == r(code, data=True)
		assert "0.0" == r(code, data=False)
		assert "42.0" == r(code, data=42)
		assert "42.0" == r(code, data="42")

		# Make sure that the parameters have the same name in all implementations
		assert "42.0" == r("<?print float(obj=data)?>", data=42)
	else:
		assert 0.0 == eval(r("<?print float()?>"))
		assert 1.0 == eval(r(code, data=True))
		assert 0.0 == eval(r(code, data=False))
		assert 42.0 == eval(r(code, data=42))
		assert 42.0 == eval(r(code, data="42"))

		# Make sure that the parameters have the same name in all implementations
		assert 42.0 == eval(r("<?print float(obj=data)?>", data=42))


@pytest.mark.ul4
def test_function_len(r):
	code = "<?print len(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print len()?>")
	with raises(argumentmismatchmessage):
		r("<?print len(1, 2)?>")
	with raises("has no len\\(\\)|len\\(.*\\) not supported"):
		r(code, data=None)
	with raises("has no len\\(\\)|len\\(.*\\) not supported"):
		r(code, data=True)
	with raises("has no len\\(\\)|len\\(.*\\) not supported"):
		r(code, data=False)
	with raises("has no len\\(\\)|len\\(.*\\) not supported"):
		r(code, data=42)
	with raises("has no len\\(\\)|len\\(.*\\) not supported"):
		r(code, data=4.2)
	assert "42" == r(code, data=42*"?")
	assert "42" == r(code, data=42*[None])
	assert "42" == r(code, data=dict.fromkeys(range(42)))

	# Make sure that the parameters have the same name in all implementations
	assert "42" == r("<?print len(sequence=data)?>", data=42*"?")


@pytest.mark.ul4
def test_function_any(r):
	with raises(argumentmismatchmessage):
		r("<?print any()?>")
	with raises(argumentmismatchmessage):
		r("<?print any(1, 2)?>")
	with raises("is not iterable|any\\(.*\\) not supported"):
		r("<?print any(data)?>", data=None)
	assert "False" == r("<?print any('')?>")
	assert "True" == r("<?print any('foo')?>")
	assert "True" == r("<?print any(i > 7 for i in range(10))?>")
	assert "False" == r("<?print any(i > 17 for i in range(10))?>")

	# Make sure that the parameters have the same name in all implementations
	assert "False" == r("<?print any(iterable=(i > 17 for i in range(10)))?>")


@pytest.mark.ul4
def test_function_all(r):
	with raises(argumentmismatchmessage):
		r("<?print all()?>")
	with raises(argumentmismatchmessage):
		r("<?print all(1, 2)?>")
	with raises("is not iterable|all\\(.*\\) not supported"):
		r("<?print all(data)?>", data=None)
	assert "True" == r("<?print all('')?>")
	assert "True" == r("<?print all('foo')?>")
	assert "False" == r("<?print all(i < 7 for i in range(10))?>")
	assert "True" == r("<?print all(i < 17 for i in range(10))?>")

	# Make sure that the parameters have the same name in all implementations
	assert "True" == r("<?print all(iterable=(i < 17 for i in range(10)))?>")


@pytest.mark.ul4
def test_function_enumerate(r):
	code1 = "<?for (i, value) in enumerate(data)?>(<?print value?>=<?print i?>)<?end for?>"
	code2 = "<?for (i, value) in enumerate(data, 42)?>(<?print value?>=<?print i?>)<?end for?>"

	with raises(argumentmismatchmessage):
		r("<?print enumerate()?>")
	with raises(argumentmismatchmessage):
		r("<?print enumerate(1, 2, 3)?>")
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code1, data=None)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code1, data=True)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code1, data=False)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code1, data=42)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code1, data=4.2)
	assert "(f=0)(o=1)(o=2)" == r(code1, data="foo")
	assert "(foo=0)(bar=1)" == r(code1, data=["foo", "bar"])
	assert "(foo=0)" == r(code1, data=dict(foo=True))
	assert "" == r(code1, data="")
	assert "(f=42)(o=43)(o=44)" == r(code2, data="foo")

	# Make sure that the parameters have the same name in all implementations
	assert "(f=42)(o=43)(o=44)" == r("<?for (i, value) in enumerate(iterable=data, start=42)?>(<?print value?>=<?print i?>)<?end for?>", data="foo")


@pytest.mark.ul4
def test_function_enumfl(r):
	code1 = "<?for (i, f, l, value) in enumfl(data)?><?if f?>[<?end if?>(<?print value?>=<?print i?>)<?if l?>]<?end if?><?end for?>"
	code2 = "<?for (i, f, l, value) in enumfl(data, 42)?><?if f?>[<?end if?>(<?print value?>=<?print i?>)<?if l?>]<?end if?><?end for?>"

	with raises(argumentmismatchmessage):
		r("<?print enumfl()?>")
	with raises(argumentmismatchmessage):
		r("<?print enumfl(1, 2, 3)?>")
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code1, data=None)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code1, data=True)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code1, data=False)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code1, data=42)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code1, data=4.2)
	assert "[(f=0)(o=1)(o=2)]" == r(code1, data="foo")
	assert "[(foo=0)(bar=1)]" == r(code1, data=["foo", "bar"])
	assert "[(foo=0)]" == r(code1, data=dict(foo=True))
	assert "" == r(code1, data="")
	assert "[(f=42)(o=43)(o=44)]" == r(code2, data="foo")

	# Make sure that the parameters have the same name in all implementations
	assert "[(f=42)(o=43)(o=44)]" == r("<?for (i, f, l, value) in enumfl(iterable=data, start=42)?><?if f?>[<?end if?>(<?print value?>=<?print i?>)<?if l?>]<?end if?><?end for?>", data="foo")


@pytest.mark.ul4
def test_function_isfirstlast(r):
	code = "<?for (f, l, value) in isfirstlast(data)?><?if f?>[<?end if?>(<?print value?>)<?if l?>]<?end if?><?end for?>"

	with raises(argumentmismatchmessage):
		r("<?print isfirstlast()?>")
	with raises(argumentmismatchmessage):
		r("<?print isfirstlast(1, 2)?>")
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code, data=None)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code, data=True)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code, data=False)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code, data=42)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code, data=4.2)
	assert "[(f)(o)(o)]" == r(code, data="foo")
	assert "[(foo)(bar)]" == r(code, data=["foo", "bar"])
	assert "[(foo)]" == r(code, data=dict(foo=True))
	assert "" == r(code, data="")

	# Make sure that the parameters have the same name in all implementations
	assert "[(f)(o)(o)]" == r("<?for (f, l, value) in isfirstlast(iterable=data)?><?if f?>[<?end if?>(<?print value?>)<?if l?>]<?end if?><?end for?>", data="foo")


@pytest.mark.ul4
def test_function_isfirst(r):
	code = "<?for (f, value) in isfirst(data)?><?if f?>[<?end if?>(<?print value?>)<?end for?>"

	with raises(argumentmismatchmessage):
		r("<?print isfirst()?>")
	with raises(argumentmismatchmessage):
		r("<?print isfirst(1, 2)?>")
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code, data=None)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code, data=True)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code, data=False)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code, data=42)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code, data=4.2)
	assert "[(f)(o)(o)" == r(code, data="foo")
	assert "[(foo)(bar)" == r(code, data=["foo", "bar"])
	assert "[(foo)" == r(code, data=dict(foo=True))
	assert "" == r(code, data="")

	# Make sure that the parameters have the same name in all implementations
	assert "[(f)(o)(o)" == r("<?for (f, value) in isfirst(iterable=data)?><?if f?>[<?end if?>(<?print value?>)<?end for?>", data="foo")


@pytest.mark.ul4
def test_function_islast(r):
	code = "<?for (l, value) in islast(data)?>(<?print value?>)<?if l?>]<?end if?><?end for?>"

	with raises(argumentmismatchmessage):
		r("<?print islast()?>")
	with raises(argumentmismatchmessage):
		r("<?print islast(1, 2)?>")
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code, data=None)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code, data=True)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code, data=False)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code, data=42)
	with raises("is not iterable|iter\\(.*\\) not supported"):
		r(code, data=4.2)
	assert "(f)(o)(o)]" == r(code, data="foo")
	assert "(foo)(bar)]" == r(code, data=["foo", "bar"])
	assert "(foo)]" == r(code, data=dict(foo=True))
	assert "" == r(code, data="")

	# Make sure that the parameters have the same name in all implementations
	assert "(f)(o)(o)]" == r("<?for (l, value) in islast(iterable=data)?>(<?print value?>)<?if l?>]<?end if?><?end for?>", data="foo")


@pytest.mark.ul4
def test_function_isundefined(r):
	code = "<?print isundefined(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print isundefined()?>")
	with raises(argumentmismatchmessage):
		r("<?print isundefined(1, 2)?>")
	assert "True" == r(code)
	assert "False" == r(code, data=None)
	assert "False" == r(code, data=True)
	assert "False" == r(code, data=False)
	assert "False" == r(code, data=42)
	assert "False" == r(code, data=4.2)
	assert "False" == r(code, data="foo")
	assert "False" == r(code, data=datetime.datetime.now())
	assert "False" == r(code, data=datetime.timedelta(1))
	assert "False" == r(code, data=misc.monthdelta(1))
	assert "False" == r(code, data=())
	assert "False" == r(code, data=[])
	assert "False" == r(code, data={})
	assert "False" == r("<?print isundefined(repr)?>")
	assert "False" == r(code, data=ul4c.Template(""))
	assert "False" == r(code, data=color.red)

	# Make sure that the parameters have the same name in all implementations
	assert "False" == r("<?print isundefined(obj=data)?>", data=None)


@pytest.mark.ul4
def test_function_isdefined(r):
	code = "<?print isdefined(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print isdefined()?>")
	with raises(argumentmismatchmessage):
		r("<?print isdefined(1, 2)?>")
	assert "False" == r(code)
	assert "True" == r(code, data=None)
	assert "True" == r(code, data=True)
	assert "True" == r(code, data=False)
	assert "True" == r(code, data=42)
	assert "True" == r(code, data=4.2)
	assert "True" == r(code, data="foo")
	assert "True" == r(code, data=datetime.datetime.now())
	assert "True" == r(code, data=datetime.timedelta(1))
	assert "True" == r(code, data=misc.monthdelta(1))
	assert "True" == r(code, data=())
	assert "True" == r(code, data=[])
	assert "True" == r(code, data={})
	assert "True" == r(code, data=ul4c.Template(""))
	assert "True" == r("<?print isdefined(repr)?>")
	assert "True" == r(code, data=color.red)

	# Make sure that the parameters have the same name in all implementations
	assert "True" == r("<?print isdefined(obj=data)?>", data=None)


@pytest.mark.ul4
def test_function_isnone(r):
	code = "<?print isnone(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print isnone()?>")
	with raises(argumentmismatchmessage):
		r("<?print isnone(1, 2)?>")
	assert "False" == r(code)
	assert "True" == r(code, data=None)
	assert "False" == r(code, data=True)
	assert "False" == r(code, data=False)
	assert "False" == r(code, data=42)
	assert "False" == r(code, data=4.2)
	assert "False" == r(code, data="foo")
	assert "False" == r(code, data=datetime.datetime.now())
	assert "False" == r(code, data=datetime.timedelta(1))
	assert "False" == r(code, data=misc.monthdelta(1))
	assert "False" == r(code, data=())
	assert "False" == r(code, data=[])
	assert "False" == r(code, data={})
	assert "False" == r(code, data=ul4c.Template(""))
	assert "False" == r("<?print isnone(repr)?>")
	assert "False" == r(code, data=color.red)

	# Make sure that the parameters have the same name in all implementations
	assert "True" == r("<?print isnone(obj=data)?>", data=None)


@pytest.mark.ul4
def test_function_isbool(r):
	code = "<?print isbool(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print isbool()?>")
	with raises(argumentmismatchmessage):
		r("<?print isbool(1, 2)?>")
	assert "False" == r(code)
	assert "False" == r(code, data=None)
	assert "True" == r(code, data=True)
	assert "True" == r(code, data=False)
	assert "False" == r(code, data=42)
	assert "False" == r(code, data=4.2)
	assert "False" == r(code, data="foo")
	assert "False" == r(code, data=datetime.datetime.now())
	assert "False" == r(code, data=datetime.timedelta(1))
	assert "False" == r(code, data=misc.monthdelta(1))
	assert "False" == r(code, data=())
	assert "False" == r(code, data=[])
	assert "False" == r(code, data={})
	assert "False" == r(code, data=ul4c.Template(""))
	assert "False" == r("<?print isbool(repr)?>")
	assert "False" == r(code, data=color.red)

	# Make sure that the parameters have the same name in all implementations
	assert "False" == r("<?print isbool(obj=data)?>", data=None)


@pytest.mark.ul4
def test_function_isint(r):
	code = "<?print isint(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print isint()?>")
	with raises(argumentmismatchmessage):
		r("<?print isint(1, 2)?>")
	assert "False" == r(code)
	assert "False" == r(code, data=None)
	assert "False" == r(code, data=True)
	assert "False" == r(code, data=False)
	assert "True" == r(code, data=42)
	assert "False" == r(code, data=4.2)
	assert "False" == r(code, data="foo")
	assert "False" == r(code, data=datetime.datetime.now())
	assert "False" == r(code, data=datetime.timedelta(1))
	assert "False" == r(code, data=misc.monthdelta(1))
	assert "False" == r(code, data=())
	assert "False" == r(code, data=[])
	assert "False" == r(code, data={})
	assert "False" == r(code, data=ul4c.Template(""))
	assert "False" == r("<?print isint(repr)?>")
	assert "False" == r(code, data=color.red)

	# Make sure that the parameters have the same name in all implementations
	assert "False" == r("<?print isint(obj=data)?>", data=None)


@pytest.mark.ul4
def test_function_isfloat(r):
	code = "<?print isfloat(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print isfloat()?>")
	with raises(argumentmismatchmessage):
		r("<?print isfloat(1, 2)?>")
	assert "False" == r(code)
	assert "False" == r(code, data=None)
	assert "False" == r(code, data=True)
	assert "False" == r(code, data=False)
	assert "False" == r(code, data=42)
	assert "True" == r(code, data=4.2)
	assert "False" == r(code, data="foo")
	assert "False" == r(code, data=datetime.datetime.now())
	assert "False" == r(code, data=datetime.timedelta(1))
	assert "False" == r(code, data=misc.monthdelta(1))
	assert "False" == r(code, data=())
	assert "False" == r(code, data=[])
	assert "False" == r(code, data={})
	assert "False" == r(code, data=ul4c.Template(""))
	assert "False" == r("<?print isfloat(repr)?>")
	assert "False" == r(code, data=color.red)

	# Make sure that the parameters have the same name in all implementations
	assert "False" == r("<?print isfloat(obj=data)?>", data=None)


@pytest.mark.ul4
def test_function_isstr(r):
	code = "<?print isstr(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print isstr()?>")
	with raises(argumentmismatchmessage):
		r("<?print isstr(1, 2)?>")
	assert "False" == r(code)
	assert "False" == r(code, data=None)
	assert "False" == r(code, data=True)
	assert "False" == r(code, data=False)
	assert "False" == r(code, data=42)
	assert "False" == r(code, data=4.2)
	assert "True" == r(code, data="foo")
	assert "False" == r(code, data=datetime.datetime.now())
	assert "False" == r(code, data=datetime.timedelta(1))
	assert "False" == r(code, data=misc.monthdelta(1))
	assert "False" == r(code, data=())
	assert "False" == r(code, data=[])
	assert "False" == r(code, data={})
	assert "False" == r(code, data=ul4c.Template(""))
	assert "False" == r("<?print isstr(repr)?>")
	assert "False" == r(code, data=color.red)

	# Make sure that the parameters have the same name in all implementations
	assert "False" == r("<?print isstr(obj=data)?>", data=None)


@pytest.mark.ul4
def test_function_isdate(r):
	code = "<?print isdate(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print isdate()?>")
	with raises(argumentmismatchmessage):
		r("<?print isdate(1, 2)?>")
	assert "False" == r(code)
	assert "False" == r(code, data=None)
	assert "False" == r(code, data=True)
	assert "False" == r(code, data=False)
	assert "False" == r(code, data=42)
	assert "False" == r(code, data=4.2)
	assert "False" == r(code, data="foo")
	assert "True" == r(code, data=datetime.datetime.now())
	assert "False" == r(code, data=datetime.timedelta(1))
	assert "False" == r(code, data=misc.monthdelta(1))
	assert "False" == r(code, data=())
	assert "False" == r(code, data=[])
	assert "False" == r(code, data={})
	assert "False" == r(code, data=ul4c.Template(""))
	assert "False" == r("<?print isdate(repr)?>")
	assert "False" == r(code, data=color.red)

	# Make sure that the parameters have the same name in all implementations
	assert "False" == r("<?print isdate(obj=data)?>", data=None)


@pytest.mark.ul4
def test_function_islist(r):
	code = "<?print islist(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print islist()?>")
	with raises(argumentmismatchmessage):
		r("<?print islist(1, 2)?>")
	assert "False" == r(code)
	assert "False" == r(code, data=None)
	assert "False" == r(code, data=True)
	assert "False" == r(code, data=False)
	assert "False" == r(code, data=42)
	assert "False" == r(code, data=4.2)
	assert "False" == r(code, data="foo")
	assert "False" == r(code, data=datetime.datetime.now())
	assert "False" == r(code, data=datetime.timedelta(1))
	assert "False" == r(code, data=misc.monthdelta(1))
	assert "True" == r(code, data=())
	assert "True" == r(code, data=[])
	assert "True" == r(code, data=PseudoList([]))
	if r is not render_php:
		assert "False" == r(code, data={})
	assert "False" == r(code, data=ul4c.Template(""))
	assert "False" == r("<?print islist(repr)?>")
	assert "False" == r(code, data=color.red)

	# Make sure that the parameters have the same name in all implementations
	assert "False" == r("<?print islist(obj=data)?>", data=None)


@pytest.mark.ul4
def test_function_isdict(r):
	code = "<?print isdict(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print isdict()?>")
	with raises(argumentmismatchmessage):
		r("<?print isdict(1, 2)?>")
	assert "False" == r(code)
	assert "False" == r(code, data=None)
	assert "False" == r(code, data=True)
	assert "False" == r(code, data=False)
	assert "False" == r(code, data=42)
	assert "False" == r(code, data=4.2)
	assert "False" == r(code, data="foo")
	assert "False" == r(code, data=datetime.datetime.now())
	assert "False" == r(code, data=datetime.timedelta(1))
	assert "False" == r(code, data=misc.monthdelta(1))
	if r is not render_php:
		assert "False" == r(code, data=())
		assert "False" == r(code, data=[])
	assert "True" == r(code, data={})
	assert "True" == r(code, data=PseudoDict({}))
	assert "False" == r(code, data=ul4c.Template(""))
	assert "False" == r("<?print isdict(repr)?>")
	assert "False" == r(code, data=color.red)

	# Make sure that the parameters have the same name in all implementations
	assert "False" == r("<?print isdict(obj=data)?>", data=None)


@pytest.mark.ul4
def test_function_istemplate(r):
	code = "<?print istemplate(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print istemplate()?>")
	with raises(argumentmismatchmessage):
		r("<?print istemplate(1, 2)?>")
	assert "False" == r(code)
	assert "False" == r(code, data=None)
	assert "False" == r(code, data=True)
	assert "False" == r(code, data=False)
	assert "False" == r(code, data=42)
	assert "False" == r(code, data=4.2)
	assert "False" == r(code, data="foo")
	assert "False" == r(code, data=datetime.datetime.now())
	assert "False" == r(code, data=datetime.timedelta(1))
	assert "False" == r(code, data=misc.monthdelta(1))
	assert "False" == r(code, data=())
	assert "False" == r(code, data=[])
	assert "False" == r(code, data={})
	assert "True" == r(code, data=ul4c.Template(""))
	assert "False" == r("<?print istemplate(repr)?>")
	assert "False" == r(code, data=color.red)

	# Make sure that the parameters have the same name in all implementations
	assert "False" == r("<?print istemplate(obj=data)?>", data=None)


@pytest.mark.ul4
def test_function_isfunction(r):
	code = "<?print isfunction(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print isfunction()?>")
	with raises(argumentmismatchmessage):
		r("<?print isfunction(1, 2)?>")
	assert "False" == r(code)
	assert "False" == r(code, data=None)
	assert "False" == r(code, data=True)
	assert "False" == r(code, data=False)
	assert "False" == r(code, data=42)
	assert "False" == r(code, data=4.2)
	assert "False" == r(code, data="foo")
	assert "False" == r(code, data=datetime.datetime.now())
	assert "False" == r(code, data=datetime.timedelta(1))
	assert "False" == r(code, data=misc.monthdelta(1))
	assert "False" == r(code, data=())
	assert "False" == r(code, data=[])
	assert "False" == r(code, data={})
	assert "True" == r(code, data=ul4c.Template(""))
	assert "True" == r("<?print isfunction(repr)?>")
	assert "True" == r("<?def f?><?return 42?><?end def?><?print isfunction(f)?>")
	assert "False" == r(code, data=color.red)

	# Make sure that the parameters have the same name in all implementations
	assert "False" == r("<?print istemplate(obj=data)?>", data=None)


@pytest.mark.ul4
def test_function_iscolor(r):
	code = "<?print iscolor(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print iscolor()?>")
	with raises(argumentmismatchmessage):
		r("<?print iscolor(1, 2)?>")
	assert "False" == r(code)
	assert "False" == r(code, data=None)
	assert "False" == r(code, data=True)
	assert "False" == r(code, data=False)
	assert "False" == r(code, data=42)
	assert "False" == r(code, data=4.2)
	assert "False" == r(code, data="foo")
	assert "False" == r(code, data=datetime.datetime.now())
	assert "False" == r(code, data=datetime.timedelta(1))
	assert "False" == r(code, data=misc.monthdelta(1))
	assert "False" == r(code, data=())
	assert "False" == r(code, data=[])
	assert "False" == r(code, data={})
	assert "False" == r(code, data=ul4c.Template(""))
	assert "False" == r("<?print iscolor(repr)?>")
	assert "True" == r(code, data=color.red)

	# Make sure that the parameters have the same name in all implementations
	assert "False" == r("<?print iscolor(obj=data)?>", data=None)


@pytest.mark.ul4
def test_function_istimedelta(r):
	code = "<?print istimedelta(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print istimedelta()?>")
	with raises(argumentmismatchmessage):
		r("<?print istimedelta(1, 2)?>")
	assert "False" == r(code)
	assert "False" == r(code, data=None)
	assert "False" == r(code, data=True)
	assert "False" == r(code, data=False)
	assert "False" == r(code, data=42)
	assert "False" == r(code, data=4.2)
	assert "False" == r(code, data="foo")
	assert "False" == r(code, data=datetime.datetime.now())
	assert "True" == r(code, data=datetime.timedelta(1))
	assert "False" == r(code, data=misc.monthdelta(1))
	assert "False" == r(code, data=())
	assert "False" == r(code, data=[])
	assert "False" == r(code, data={})
	assert "False" == r(code, data=ul4c.Template(""))
	assert "False" == r("<?print istimedelta(repr)?>")
	assert "False" == r(code, data=color.red)

	# Make sure that the parameters have the same name in all implementations
	assert "False" == r("<?print istimedelta(obj=data)?>", data=None)


@pytest.mark.ul4
def test_function_ismonthdelta(r):
	code = "<?print ismonthdelta(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print ismonthdelta()?>")
	with raises(argumentmismatchmessage):
		r("<?print ismonthdelta(1, 2)?>")
	assert "False" == r(code)
	assert "False" == r(code, data=None)
	assert "False" == r(code, data=True)
	assert "False" == r(code, data=False)
	assert "False" == r(code, data=42)
	assert "False" == r(code, data=4.2)
	assert "False" == r(code, data="foo")
	assert "False" == r(code, data=datetime.datetime.now())
	assert "False" == r(code, data=datetime.timedelta(1))
	assert "True" == r(code, data=misc.monthdelta(1))
	assert "False" == r(code, data=())
	assert "False" == r(code, data=[])
	assert "False" == r(code, data={})
	assert "False" == r(code, data=ul4c.Template(""))
	assert "False" == r("<?print ismonthdelta(repr)?>")
	assert "False" == r(code, data=color.red)

	# Make sure that the parameters have the same name in all implementations
	assert "False" == r("<?print ismonthdelta(obj=data)?>", data=None)


@pytest.mark.ul4
def test_function_repr(r):
	code = "<?print repr(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print repr()?>")
	with raises(argumentmismatchmessage):
		r("<?print repr(1, 2)?>")
	assert "None" == r(code, data=None)
	assert "True" == r(code, data=True)
	assert "False" == r(code, data=False)
	assert "42" == r(code, data=42)
	assert 42.5 == eval(r(code, data=42.5))
	assert r(code, data="foo") in ('"foo"', "'foo'")
	assert [1, 2, 3] == eval(r(code, data=[1, 2, 3]))
	if r is not render_js:
		assert [1, 2, 3] == eval(r(code, data=(1, 2, 3)))
	assert {"a": 1, "b": 2} == eval(r(code, data={"a": 1, "b": 2}))
	if r is not render_php:
		assert "@(2011-02-07T12:34:56.123000)" == r(code, data=datetime.datetime(2011, 2, 7, 12, 34, 56, 123000))
	assert "@(2011-02-07T12:34:56)" == r(code, data=datetime.datetime(2011, 2, 7, 12, 34, 56))
	assert "@(2011-02-07)" == r(code, data=datetime.datetime(2011, 2, 7))
	assert "@(2011-02-07)" == r(code, data=datetime.date(2011, 2, 7))
	assert "timedelta(1)" == r(code, data=datetime.timedelta(1))
	assert "timedelta(0, 1)" == r(code, data=datetime.timedelta(0, 1))
	assert "timedelta(0, 0, 1)" == r(code, data=datetime.timedelta(0, 0, 1))
	assert "timedelta(-1)" == r(code, data=datetime.timedelta(-1))
	assert "timedelta(-1, 86399)" == r(code, data=datetime.timedelta(0, -1))
	assert "timedelta(-1, 86399, 999999)" == r(code, data=datetime.timedelta(0, 0, -1))
	assert "timedelta(0, 43200)" == r(code, data=datetime.timedelta(0.5))
	assert "timedelta(0, 0, 500000)" == r(code, data=datetime.timedelta(0, 0.5))
	assert "timedelta(-1, 43200)" == r(code, data=datetime.timedelta(-0.5))
	assert "timedelta(-1, 86399, 500000)" == r(code, data=datetime.timedelta(0, -0.5))

	# Make sure that the parameters have the same name in all implementations
	assert "None" == r("<?print repr(obj=data)?>", data=None)


@pytest.mark.ul4
def test_function_print(r):
	assert "gurk hurz hinz kunz" == r("<?code print('gurk', 'hurz', 'hinz', 'kunz')?>")


@pytest.mark.ul4
def test_function_printx(r):
	assert "&lt;gurk&gt; &lt;hurz&gt; &lt;hinz&gt; &lt;kunz&gt;" == r("<?code printx('<gurk>', '<hurz>', '<hinz>', '<kunz>')?>")


@pytest.mark.ul4
def test_function_format_date(r):
	t = datetime.datetime(2011, 1, 25, 13, 34, 56, 987000)
	code2 = "<?print format(data, fmt)?>"
	code3 = "<?print format(data, fmt, lang)?>"

	assert "2011" == r(code2, fmt="%Y", data=t)
	assert "01" == r(code2, fmt="%m", data=t)
	assert "25" == r(code2, fmt="%d", data=t)
	assert "13" == r(code2, fmt="%H", data=t)
	assert "34" == r(code2, fmt="%M", data=t)
	assert "56" == r(code2, fmt="%S", data=t)
	assert "987000" == r(code2, fmt="%f", data=t)
	assert "Tue" == r(code2, fmt="%a", data=t)
	assert "Tue" == r(code3, fmt="%a", data=t, lang=None)
	assert "Tue" == r(code3, fmt="%a", data=t, lang="en")
	assert "Di" == r(code3, fmt="%a", data=t, lang="de")
	assert "Di" == r(code3, fmt="%a", data=t, lang="de_DE")
	assert "Tuesday" == r(code2, fmt="%A", data=t)
	assert "Tuesday" == r(code3, fmt="%A", data=t, lang=None)
	assert "Tuesday" == r(code3, fmt="%A", data=t, lang="en")
	assert "Dienstag" == r(code3, fmt="%A", data=t, lang="de")
	assert "Dienstag" == r(code3, fmt="%A", data=t, lang="de_DE")
	assert "Jan" == r(code2, fmt="%b", data=t)
	assert "Jan" == r(code3, fmt="%b", data=t, lang=None)
	assert "Jan" == r(code3, fmt="%b", data=t, lang="en")
	assert "Jan" == r(code3, fmt="%b", data=t, lang="de")
	assert "Jan" == r(code3, fmt="%b", data=t, lang="de_DE")
	assert "January" == r(code2, fmt="%B", data=t)
	assert "January" == r(code3, fmt="%B", data=t, lang=None)
	assert "January" == r(code3, fmt="%B", data=t, lang="en")
	assert "Januar" == r(code3, fmt="%B", data=t, lang="de")
	assert "Januar" == r(code3, fmt="%B", data=t, lang="de_DE")
	assert "01" == r(code2, fmt="%I", data=t)
	assert "025" == r(code2, fmt="%j", data=t)
	assert "PM" == r(code2, fmt="%p", data=t)
	assert "04" == r(code2, fmt="%U", data=t)
	assert "2" == r(code2, fmt="%w", data=t)
	assert "04" == r(code2, fmt="%W", data=t)
	assert "11" == r(code2, fmt="%y", data=t)
	assert r(code2, fmt="%c", data=t) in ("Tue Jan 25 13:34:56 2011", "Tue 25 Jan 2011 01:34:56 PM", "Tue 25 Jan 2011 01:34:56 PM ")
	assert "01/25/2011" == r(code2, fmt="%x", data=t)
	assert "01/25/2011" == r(code3, fmt="%x", data=t, lang=None)
	assert "01/25/2011" == r(code3, fmt="%x", data=t, lang="en")
	assert "25.01.2011" == r(code3, fmt="%x", data=t, lang="de")
	assert "25.01.2011" == r(code3, fmt="%x", data=t, lang="de_DE")
	assert r(code2, fmt="%X", data=t) in ("13:34:56", "01:34:56 PM")
	assert r(code3, fmt="%X", data=t, lang=None) in ("13:34:56", "01:34:56 PM")
	assert r(code3, fmt="%X", data=t, lang="en") in ("13:34:56", "01:34:56 PM")
	assert "13:34:56" == r(code3, fmt="%X", data=t, lang="de")
	assert "13:34:56" == r(code3, fmt="%X", data=t, lang="de_DE")
	assert "%" == r(code2, fmt="%%", data=t)


@pytest.mark.ul4
def test_function_format_int(r):
	code2 = "<?print format(data, fmt)?>"
	code3 = "<?print format(data, fmt, lang)?>"

	formatstrings = [
		"",
		"",
		"5",
		"05",
		"05",
		"+05",
		"+8b",
		"+#10b",
		"o",
		"+#x",
		"+#X",
		"<5",
		">5",
		"?>5",
		"^5",
		"?= 5",
		"?= #11b",
	]

	for f in formatstrings:
		assert format(42, f) == r(code2, data=42, fmt=f)
		if "c" not in f:
			assert format(-42, f) == r(code2, data=-42, fmt=f)
	assert format(True, "05") == r(code2, data=True, fmt="05")


@pytest.mark.ul4
def test_function_format_kwargs(r):
	assert "42" == r("<?print format(obj=data, fmt=fmt, lang=lang)?>", fmt="", data=42, lang="de")


@pytest.mark.ul4
def test_function_chr(r):
	code = "<?print chr(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print chr()?>")
	with raises(argumentmismatchmessage):
		r("<?print chr(1, 2)?>")
	assert "\x00" == r(code, data=0)
	assert "a" == r(code, data=ord("a"))
	assert "\u20ac" == r(code, data=0x20ac)

	# Make sure that the parameters have the same name in all implementations
	assert "\x00" == r("<?print chr(i=data)?>", data=0)


@pytest.mark.ul4
def test_function_ord(r):
	code = "<?print ord(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print ord()?>")
	with raises(argumentmismatchmessage):
		r("<?print ord(1, 2)?>")
	assert "0" == r(code, data="\x00")
	assert str(ord("a")) == r(code, data="a")
	assert str(0x20ac) == r(code, data="\u20ac")

	# Make sure that the parameters have the same name in all implementations
	assert "0" == r("<?print ord(c=data)?>", data="\x00")


@pytest.mark.ul4
def test_function_hex(r):
	code = "<?print hex(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print hex()?>")
	with raises(argumentmismatchmessage):
		r("<?print hex(1, 2)?>")
	assert "0x0" == r(code, data=0)
	assert "0xff" == r(code, data=0xff)
	assert "0xffff" == r(code, data=0xffff)
	assert "-0xffff" == r(code, data=-0xffff)

	# Make sure that the parameters have the same name in all implementations
	assert "0x0" == r("<?print hex(number=data)?>", data=0)


@pytest.mark.ul4
def test_function_oct(r):
	code = "<?print oct(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print oct()?>")
	with raises(argumentmismatchmessage):
		r("<?print oct(1, 2)?>")
	assert "0o0" == r(code, data=0)
	assert "0o77" == r(code, data=0o77)
	assert "0o7777" == r(code, data=0o7777)
	assert "-0o7777" == r(code, data=-0o7777)

	# Make sure that the parameters have the same name in all implementations
	assert "0o0" == r("<?print oct(number=data)?>", data=0)


@pytest.mark.ul4
def test_function_bin(r):
	code = "<?print bin(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print bin()?>")
	with raises(argumentmismatchmessage):
		r("<?print bin(1, 2)?>")
	assert "0b0" == r(code, data=0b0)
	assert "0b11" == r(code, data=0b11)
	assert "-0b1111" == r(code, data=-0b1111)


@pytest.mark.ul4
def test_function_bin_kwargs(r):
	assert "0b0" == r("<?print bin(number=data)?>", data=0)


@pytest.mark.ul4
def test_function_abs(r):
	code = "<?print abs(data)?>"

	with raises(argumentmismatchmessage):
		r("<?print abs()?>")
	with raises(argumentmismatchmessage):
		r("<?print abs(1, 2)?>")
	assert "0" == r(code, data=0)
	assert "42" == r(code, data=42)
	assert "42" == r(code, data=-42)
	assert "1 month" == r(code, data=misc.monthdelta(-1))
	assert "1 day, 0:00:01.000001" == r(code, data=datetime.timedelta(-1, -1, -1))

	# Make sure that the parameters have the same name in all implementations
	assert "0" == r("<?print abs(number=data)?>", data=0)


@pytest.mark.ul4
def test_function_sorted(r):
	code = "<?for i in sorted(data)?><?print i?><?end for?>"

	with raises(argumentmismatchmessage):
		r("<?print sorted()?>")
	assert "gkru" == r(code, data="gurk")
	assert "24679" == r(code, data="92746")
	assert "172342" == r(code, data=(42, 17, 23))
	assert "012" == r(code, data={0: "zero", 1: "one", 2: "two"})

	# Make sure that the parameters have the same name in all implementations
	assert "123" == r("<?for i in sorted(iterable=data)?><?print i?><?end for?>", data="321")


@pytest.mark.ul4
def test_function_range(r):
	code1 = "<?for i in range(data)?><?print i?>;<?end for?>"
	code2 = "<?for i in range(data[0], data[1])?><?print i?>;<?end for?>"
	code3 = "<?for i in range(data[0], data[1], data[2])?><?print i?>;<?end for?>"

	with raises(argumentmismatchmessage):
		r("<?print range()?>")
	with raises(argumentmismatchmessage):
		r("<?print range(1, 2, 3, 4)?>")
	assert "" == r(code1, data=-10)
	assert "" == r(code1, data=0)
	assert "0;" == r(code1, data=1)
	assert "0;1;2;3;4;" == r(code1, data=5)
	assert "" == r(code2, data=[0, -10])
	assert "" == r(code2, data=[0, 0])
	assert "0;1;2;3;4;" == r(code2, data=[0, 5])
	assert "-5;-4;-3;-2;-1;0;1;2;3;4;" == r(code2, data=[-5, 5])
	assert "" == r(code3, data=[0, -10, 1])
	assert "" == r(code3, data=[0, 0, 1])
	assert "0;2;4;6;8;" == r(code3, data=[0, 10, 2])
	assert "" == r(code3, data=[0, 10, -2])
	assert "10;8;6;4;2;" == r(code3, data=[10, 0, -2])
	assert "" == r(code3, data=[10, 0, 2])


@pytest.mark.ul4
def test_function_slice(r):
	code2 = "<?for i in slice(data[0], data[1])?><?print i?>;<?end for?>"
	code3 = "<?for i in slice(data[0], data[1], data[2])?><?print i?>;<?end for?>"
	code4 = "<?for i in slice(data[0], data[1], data[2], data[3])?><?print i?>;<?end for?>"

	with raises(argumentmismatchmessage):
		r("<?print slice(1)?>")
	with raises(argumentmismatchmessage):
		r("<?print slice(1, 2, 3, 4, 5)?>")
	assert "g;u;r;k;" == r(code2, data=("gurk", None))
	assert "g;u;" == r(code2, data=("gurk", 2))
	assert "u;r;" == r(code3, data=("gurk", 1, 3))
	assert "u;r;k;" == r(code3, data=("gurk", 1, None))
	assert "g;u;" == r(code3, data=("gurk", None, 2))
	assert "u;u;" == r(code4, data=("gurkgurk", 1, 6, 4))


@pytest.mark.ul4
def test_function_urlquote(r):
	assert "gurk" == r("<?print urlquote('gurk')?>")
	assert "%3C%3D%3E%2B%3F" == r("<?print urlquote('<=>+?')?>")
	assert "%7F%C3%BF%EF%BF%BF" == r("<?print urlquote('\u007f\u00ff\uffff')?>")

	# Make sure that the parameters have the same name in all implementations
	assert "gurk" == r("<?print urlquote(string='gurk')?>")


@pytest.mark.ul4
def test_function_urlunquote(r):
	assert "gurk" == r("<?print urlunquote('gurk')?>")
	assert "<=>+?" == r("<?print urlunquote('%3C%3D%3E%2B%3F')?>")
	assert "\u007f\u00ff\uffff" == r("<?print urlunquote('%7F%C3%BF%EF%BF%BF')?>")

	# Make sure that the parameters have the same name in all implementations
	assert "gurk" == r("<?print urlunquote(string='gurk')?>")


@pytest.mark.ul4
def test_function_zip(r):
	code0 = "<?for i in zip()?><?print i?>;<?end for?>"
	code1 = "<?for (ix, ) in zip(x)?><?print ix?>;<?end for?>"
	code2 = "<?for (ix, iy) in zip(x, y)?><?print ix?>-<?print iy?>;<?end for?>"
	code3 = "<?for (ix, iy, iz) in zip(x, y, z)?><?print ix?>-<?print iy?>+<?print iz?>;<?end for?>"

	assert "" == r(code0)
	assert "1;2;" == r(code1, x=[1, 2])
	assert "" == r(code2, x=[], y=[])
	assert "1-3;2-4;" == r(code2, x=[1, 2], y=[3, 4])
	assert "1-4;2-5;" == r(code2, x=[1, 2, 3], y=[4, 5])
	assert "" == r(code3, x=[], y=[], z=[])
	assert "1-3+5;2-4+6;" == r(code3, x=[1, 2], y=[3, 4], z=[5, 6])
	assert "1-4+6;" == r(code3, x=[1, 2, 3], y=[4, 5], z=[6])


@pytest.mark.ul4
def test_function_type(r):
	code = "<?print type(x)?>"

	with raises(argumentmismatchmessage):
		r("<?print type()?>")
	with raises(argumentmismatchmessage):
		r("<?print type(1, 2)?>")
	assert "undefined" == r(code)
	assert "none" == r(code, x=None)
	assert "bool" == r(code, x=False)
	assert "bool" == r(code, x=True)
	assert "int" == r(code, x=42)
	assert "float" == r(code, x=4.2)
	assert "str" == r(code, x="foo")
	assert "date" == r(code, x=datetime.datetime.now())
	assert "date" == r(code, x=datetime.date.today())
	assert "timedelta" == r(code, x=datetime.timedelta())
	assert "monthdelta" == r(code, x=misc.monthdelta())
	assert "list" == r(code, x=(1, 2))
	assert "list" == r(code, x=[1, 2])
	assert "list" == r(code, x=PseudoList([1, 2]))
	assert "dict" == r(code, x={1: 2})
	assert "dict" == r(code, x=PseudoDict({1: 2}))
	assert "template" == r(code, x=ul4c.Template(""))
	assert "template" == r("<?def t?><?end def?><?print type(t)?>")
	assert "function" == r("<?print type(repr)?>")
	assert "color" == r(code, x=color.red)

	# Make sure that the parameters have the same name in all implementations
	assert "none" == r("<?print type(obj=x)?>", x=None)


@pytest.mark.ul4
def test_function_reversed(r):
	code = "<?for i in reversed(x)?>(<?print i?>)<?end for?>"

	with raises(argumentmismatchmessage):
		r("<?print reversed()?>")
	with raises(argumentmismatchmessage):
		r("<?print reversed(1, 2)?>")
	assert "(3)(2)(1)" == r(code, x="123")
	assert "(3)(2)(1)" == r(code, x=[1, 2, 3])
	assert "(3)(2)(1)" == r(code, x=(1, 2, 3))

	# Make sure that the parameters have the same name in all implementations
	assert "(3)(2)(1)" == r("<?for i in reversed(sequence=x)?>(<?print i?>)<?end for?>", x=(1, 2, 3))


@pytest.mark.ul4
def test_function_min(r):
	with raises(argumentmismatchmessage):
		r("<?print min()?>")
	with raises("empty sequence"):
		r("<?print min([])?>")
	assert "1" == r("<?print min('123')?>")
	assert "1" == r("<?print min(1, 2, 3)?>")
	assert "0" == r("<?print min(0, False, 1, True)?>")
	assert "False" == r("<?print min(False, 0, True, 1)?>")
	assert "False" == r("<?print min([False, 0, True, 1])?>")


@pytest.mark.ul4
def test_function_max(r):
	with raises(argumentmismatchmessage):
		r("<?print max()?>")
	with raises("empty sequence"):
		r("<?print max([])?>")
	assert "3" == r("<?print max('123')?>")
	assert "3" == r("<?print max(1, 2, 3)?>")
	assert "1" == r("<?print max(0, False, 1, True)?>")
	assert "True" == r("<?print max(False, 0, True, 1)?>")
	assert "True" == r("<?print max([False, 0, True, 1])?>")


@pytest.mark.ul4
def test_function_sum(r):
	with raises(argumentmismatchmessage):
		r("<?print sum()?>")

	assert "0" == r("<?print sum([])?>")
	assert "6" == r("<?print sum([1, 2, 3])?>")
	assert "12" == r("<?print sum([1, 2, 3], 6)?>")
	assert "5050" == r("<?print sum(range(101))?>")

	assert "12" == r("<?print sum(iterable=[1, 2, 3], start=6)?>")


@pytest.mark.ul4
def test_function_first(r):
	assert "g" == r("<?print first('gurk')?>")
	assert "None" == r("<?print repr(first(''))?>")
	assert "x" == r("<?print first('', 'x')?>")

	assert "x" == r("<?print first(iterable='', default='x')?>")


@pytest.mark.ul4
def test_function_last(r):
	assert "k" == r("<?print last('gurk')?>")
	assert "None" == r("<?print repr(last(''))?>")
	assert "x" == r("<?print last('', 'x')?>")

	assert "x" == r("<?print last(iterable='', default='x')?>")


@pytest.mark.ul4
def test_function_rgb(r):
	assert "#369" == r("<?print repr(rgb(0.2, 0.4, 0.6))?>")
	assert "#369c" == r("<?print repr(rgb(0.2, 0.4, 0.6, 0.8))?>")

	# Make sure that the parameters have the same name in all implementations
	assert "#369c" == r("<?print repr(rgb(r=0.2, g=0.4, b=0.6, a=0.8))?>")


@pytest.mark.ul4
def test_function_hls(r):
	assert "#fff" == r("<?print repr(hls(0, 1, 0))?>")
	assert "#fff0" == r("<?print repr(hls(0, 1, 0, 0))?>")

	# Make sure that the parameters have the same name in all implementations
	assert "#fff0" == r("<?print repr(hls(h=0, l=1, s=0, a=0))?>")


@pytest.mark.ul4
def test_function_hsv(r):
	assert "#fff" == r("<?print repr(hsv(0, 0, 1))?>")
	assert "#fff0" == r("<?print repr(hsv(0, 0, 1, 0))?>")

	# Make sure that the parameters have the same name in all implementations
	assert "#fff0" == r("<?print repr(hsv(h=0, s=0, v=1, a=0))?>")


@pytest.mark.ul4
def test_method_upper(r):
	assert "GURK" == r("<?print 'gurk'.upper()?>")
	assert "GURK" == r("<?code m = 'gurk'.upper?><?print m()?>")


@pytest.mark.ul4
def test_method_lower(r):
	assert "gurk" == r("<?print 'GURK'.lower()?>")
	assert "gurk" == r("<?code m = 'GURK'.lower?><?print m()?>")


@pytest.mark.ul4
def test_method_capitalize(r):
	assert "Gurk" == r("<?print 'gURK'.capitalize()?>")
	assert "Gurk" == r("<?code m = 'gURK'.capitalize?><?print m()?>")


@pytest.mark.ul4
def test_method_startswith(r):
	assert "True" == r("<?print 'gurkhurz'.startswith('gurk')?>")
	assert "False" == r("<?print 'gurkhurz'.startswith('hurz')?>")
	assert "False" == r("<?code m = 'gurkhurz'.startswith?><?print m('hurz')?>")

	# Make sure that the parameters have the same name in all implementations
	assert "True" == r("<?print 'gurkhurz'.startswith(prefix='gurk')?>")


@pytest.mark.ul4
def test_method_endswith(r):
	assert "True" == r("<?print 'gurkhurz'.endswith('hurz')?>")
	assert "False" == r("<?print 'gurkhurz'.endswith('gurk')?>")
	assert "False" == r("<?code m = 'gurkhurz'.endswith?><?print m('gurk')?>")

	# Make sure that the parameters have the same name in all implementations
	assert "True" == r("<?print 'gurkhurz'.endswith(suffix='hurz')?>")


@pytest.mark.ul4
def test_method_strip(r):
	assert "gurk" == r(r"<?print obj.strip()?>", obj=' \t\r\ngurk \t\r\n')
	assert "gurk" == r(r"<?print obj.strip('xyz')?>", obj='xyzzygurkxyzzy')
	assert "gurk" == r(r"<?code m = obj.strip?><?print m('xyz')?>", obj='xyzzygurkxyzzy')

	# Make sure that the parameters have the same name in all implementations
	assert "gurk" == r(r"<?print obj.strip(chars='xyz')?>", obj='xyzzygurkxyzzy')


@pytest.mark.ul4
def test_method_lstrip(r):
	assert "gurk \t\r\n" == r("<?print obj.lstrip()?>", obj=" \t\r\ngurk \t\r\n")
	assert "gurkxyzzy" == r("<?print obj.lstrip(arg)?>", obj="xyzzygurkxyzzy", arg="xyz")
	assert "gurkxyzzy" == r("<?code m = obj.lstrip?><?print m(arg)?>", obj="xyzzygurkxyzzy", arg="xyz")

	# Make sure that the parameters have the same name in all implementations
	assert "gurkxyzzy" == r("<?print obj.lstrip(chars=arg)?>", obj="xyzzygurkxyzzy", arg="xyz")


@pytest.mark.ul4
def test_method_rstrip(r):
	assert " \t\r\ngurk" == r("<?print obj.rstrip()?>", obj=" \t\r\ngurk \t\r\n")
	assert "xyzzygurk" == r("<?print obj.rstrip(arg)?>", obj="xyzzygurkxyzzy", arg="xyz")
	assert "xyzzygurk" == r("<?code m = obj.rstrip?><?print m(arg)?>", obj="xyzzygurkxyzzy", arg="xyz")

	# Make sure that the parameters have the same name in all implementations
	assert "xyzzygurk" == r("<?print obj.rstrip(chars=arg)?>", obj="xyzzygurkxyzzy", arg="xyz")


@pytest.mark.ul4
def test_method_split(r):
	assert "(f)(o)(o)" == r("<?for item in obj.split()?>(<?print item?>)<?end for?>", obj=" \t\r\nf \t\r\no \t\r\no \t\r\n")
	assert "(f)(o \t\r\no \t\r\n)" == r("<?for item in obj.split(None, 1)?>(<?print item?>)<?end for?>", obj=" \t\r\nf \t\r\no \t\r\no \t\r\n")
	assert "()(f)(o)(o)()" == r("<?for item in obj.split(arg)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")
	assert "()(f)(oxxoxx)" == r("<?for item in obj.split(arg, 2)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")
	assert "()(f)(oxxoxx)" == r("<?code m = obj.split?><?for item in m(arg, 2)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")

	# Make sure that the parameters have the same name in all implementations
	assert "()(f)(oxxoxx)" == r("<?for item in obj.split(sep=arg, count=2)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")


@pytest.mark.ul4
def test_method_rsplit(r):
	assert "(f)(o)(o)" == r("<?for item in obj.rsplit()?>(<?print item?>)<?end for?>", obj=" \t\r\nf \t\r\no \t\r\no \t\r\n")
	assert "( \t\r\nf \t\r\no)(o)" == r("<?for item in obj.rsplit(None, 1)?>(<?print item?>)<?end for?>", obj=" \t\r\nf \t\r\no \t\r\no \t\r\n")
	assert "()(f)(o)(o)()" == r("<?for item in obj.rsplit(arg)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")
	assert "(xxfxxo)(o)()" == r("<?for item in obj.rsplit(arg, 2)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")
	assert "(xxfxxo)(o)()" == r("<?code m = obj.rsplit?><?for item in m(arg, 2)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")

	# Make sure that the parameters have the same name in all implementations
	assert "(xxfxxo)(o)()" == r("<?for item in obj.rsplit(sep=arg, count=2)?>(<?print item?>)<?end for?>", obj="xxfxxoxxoxx", arg="xx")


@pytest.mark.ul4
def test_method_replace(r):
	assert 'goork' == r("<?print 'gurk'.replace('u', 'oo')?>")
	assert 'fuuuu' == r("<?print 'foo'.replace('o', 'uu', None)?>")
	assert 'fuuo' == r("<?print 'foo'.replace('o', 'uu', 1)?>")
	assert 'fuuo' == r("<?code m = 'foo'.replace?><?print m('o', 'uu', 1)?>")

	# Make sure that the parameters have the same name in all implementations
	assert 'fuuo' == r("<?print 'foo'.replace(old='o', new='uu', count=1)?>")


@pytest.mark.ul4
def test_method_renders(r):
	t = ul4c.Template('(<?print data?>)')
	assert '(GURK)' == r("<?print t.renders(data='gurk').upper()?>", t=t)
	assert '(GURK)' == r("<?print t.renders(**{'data': 'gurk'}).upper()?>", t=t)
	assert '(GURK)' == r("<?code m = t.renders?><?print m(**{'data': 'gurk'}).upper()?>", t=t)

	t = ul4c.Template('(gurk)')
	assert '(GURK)' == r("<?print t.renders().upper()?>", t=t)


@pytest.mark.ul4
def test_method_mimeformat(r):
	t = datetime.datetime(2010, 2, 22, 12, 34, 56)

	assert 'Mon, 22 Feb 2010 12:34:56 GMT' == r("<?print data.mimeformat()?>", data=t)
	assert 'Mon, 22 Feb 2010 12:34:56 GMT' == r("<?code m = data.mimeformat?><?print m()?>", data=t)


@pytest.mark.ul4
def test_method_items(r):
	assert "a:42;b:17;c:23;" == r("<?for (key, value) in sorted(data.items())?><?print key?>:<?print value?>;<?end for?>", data=dict(a=42, b=17, c=23))
	assert "a:42;b:17;c:23;" == r("<?code m = data.items?><?for (key, value) in sorted(m())?><?print key?>:<?print value?>;<?end for?>", data=dict(a=42, b=17, c=23))


@pytest.mark.ul4
def test_method_values(r):
	assert "17;23;42;" == r("<?for value in sorted(data.values())?><?print value?>;<?end for?>", data=dict(a=42, b=17, c=23))
	assert "17;23;42;" == r("<?code m = data.values?><?for value in sorted(m())?><?print value?>;<?end for?>", data=dict(a=42, b=17, c=23))


@pytest.mark.ul4
def test_method_get(r):
	assert "42" == r("<?print {}.get('foo', 42)?>")
	assert "17" == r("<?print {'foo': 17}.get('foo', 42)?>")
	assert "" == r("<?print {}.get('foo')?>")
	assert "17" == r("<?print {'foo': 17}.get('foo')?>")
	assert "17" == r("<?code m = {'foo': 17}.get?><?print m('foo')?>")

	# Make sure that the parameters have the same name in all implementations
	assert "17" == r("<?print {'foo': 17}.get(key='foo', default=42)?>")


@pytest.mark.ul4
def test_method_r_g_b_a(r):
	assert '0x11' == r('<?code c = #123?><?print hex(c.r())?>')
	assert '0x11' == r('<?code c = #123?><?code m = c.r?><?print hex(m())?>')
	assert '0x22' == r('<?code c = #123?><?print hex(c.g())?>')
	assert '0x22' == r('<?code c = #123?><?code m = c.g?><?print hex(m())?>')
	assert '0x33' == r('<?code c = #123?><?print hex(c.b())?>')
	assert '0x33' == r('<?code c = #123?><?code m = c.b?><?print hex(m())?>')
	assert '0xff' == r('<?code c = #123?><?print hex(c.a())?>')
	assert '0xff' == r('<?code c = #123?><?code m = c.a?><?print hex(m())?>')


@pytest.mark.ul4
def test_method_hls(r):
	assert '0' == r('<?code c = #fff?><?print int(c.hls()[0])?>')
	assert '1' == r('<?code c = #fff?><?print int(c.hls()[1])?>')
	assert '0' == r('<?code c = #fff?><?print int(c.hls()[2])?>')
	assert '0' == r('<?code c = #fff?><?code m = c.hls?><?print int(m()[0])?>')


@pytest.mark.ul4
def test_method_hlsa(r):
	assert '0' == r('<?code c = #fff?><?print int(c.hlsa()[0])?>')
	assert '1' == r('<?code c = #fff?><?print int(c.hlsa()[1])?>')
	assert '0' == r('<?code c = #fff?><?print int(c.hlsa()[2])?>')
	assert '1' == r('<?code c = #fff?><?print int(c.hlsa()[3])?>')
	assert '0' == r('<?code c = #fff?><?code m = c.hlsa?><?print int(m()[0])?>')


@pytest.mark.ul4
def test_method_hsv(r):
	assert '0' == r('<?code c = #fff?><?print int(c.hsv()[0])?>')
	assert '0' == r('<?code c = #fff?><?print int(c.hsv()[1])?>')
	assert '1' == r('<?code c = #fff?><?print int(c.hsv()[2])?>')
	assert '0' == r('<?code c = #fff?><?code m = c.hsv?><?print int(m()[0])?>')


@pytest.mark.ul4
def test_method_hsva(r):
	assert '0' == r('<?code c = #fff?><?print int(c.hsva()[0])?>')
	assert '0' == r('<?code c = #fff?><?print int(c.hsva()[1])?>')
	assert '1' == r('<?code c = #fff?><?print int(c.hsva()[2])?>')
	assert '1' == r('<?code c = #fff?><?print int(c.hsva()[3])?>')
	assert '0' == r('<?code c = #fff?><?code m = c.hsva?><?print int(m()[0])?>')


@pytest.mark.ul4
def test_method_lum(r):
	assert 'True' == r('<?print #fff.lum() == 1?>')
	assert 'True' == r('<?code m = #fff.lum?><?print m() == 1?>')


@pytest.mark.ul4
def test_method_withlum(r):
	assert '#fff' == r('<?print #000.withlum(1)?>')
	assert '#fff' == r('<?code m = #000.withlum?><?print m(1)?>')

	# Make sure that the parameters have the same name in all implementations
	assert '#fff' == r('<?print #000.withlum(lum=1)?>')


@pytest.mark.ul4
def test_method_witha(r):
	assert '#0063a82a' == r('<?print repr(#0063a8.witha(42))?>')
	assert '#0063a82a' == r('<?code m = #0063a8.witha?><?print repr(m(42))?>')

	# Make sure that the parameters have the same name in all implementations
	assert '#0063a82a' == r('<?print repr(#0063a8.witha(a=42))?>')


@pytest.mark.ul4
def test_method_join(r):
	assert '1,2,3,4' == r('<?print ",".join("1234")?>')
	assert '1,2,3,4' == r('<?print ",".join(["1", "2", "3", "4"])?>')
	assert '1,2,3,4' == r('<?code m = ",".join?><?print m("1234")?>')

	# Make sure that the parameters have the same name in all implementations
	assert '1,2,3,4' == r('<?print ",".join(iterable="1234")?>')


@pytest.mark.ul4
def test_method_find(r):
	s = "gurkgurk"
	assert '-1' == r('<?print s.find("ks")?>', s=s)
	assert '2' == r('<?print s.find("rk")?>', s=s)
	assert '2' == r('<?print s.find("rk", 2)?>', s=s)
	assert '6' == r('<?print s.find("rk", -3)?>', s=s)
	assert '2' == r('<?print s.find("rk", 2, 4)?>', s=s)
	assert '6' == r('<?print s.find("rk", 4, 8)?>', s=s)
	assert '5' == r('<?print s.find("ur", -4, -1)?>', s=s)
	assert '-1' == r('<?print s.find("rk", 2, 3)?>', s=s)
	assert '-1' == r('<?print s.find("rk", 7)?>', s=s)
	assert '-1' == r('<?code m = s.find?><?print m("rk", 7)?>', s=s)
	l = list("gurkgurk")
	assert '-1' == r('<?print l.find("x")?>', l=l)
	assert '2' == r('<?print l.find("r")?>', l=l)
	assert '2' == r('<?print l.find("r", 2)?>', l=l)
	assert '6' == r('<?print l.find("r", -3)?>', l=l)
	assert '2' == r('<?print l.find("r", 2, 4)?>', l=l)
	assert '6' == r('<?print l.find("r", 4, 8)?>', l=l)
	assert '6' == r('<?print l.find("r", -3, -1)?>', l=l)
	assert '-1' == r('<?print l.find("r", 2, 2)?>', l=l)
	assert '-1' == r('<?print l.find("r", 7)?>', l=l)
	assert '1' == r('<?print l.find(None)?>', l=[0, None, 1, None, 2, None, 3, None])
	assert '-1' == r('<?code m = l.find?><?print m("r", 7)?>', l=l)

	# Make sure that the parameters have the same name in all implementations
	assert '2' == r('<?print s.find(sub="rk", start=2, end=4)?>', s=s)


@pytest.mark.ul4
def test_method_rfind(r):
	s = "gurkgurk"
	assert '-1' == r('<?print s.rfind("ks")?>', s=s)
	assert '6' == r('<?print s.rfind("rk")?>', s=s)
	assert '6' == r('<?print s.rfind("rk", 2)?>', s=s)
	assert '6' == r('<?print s.rfind("rk", -3)?>', s=s)
	assert '2' == r('<?print s.rfind("rk", 2, 4)?>', s=s)
	assert '6' == r('<?print s.rfind("rk", 4, 8)?>', s=s)
	assert '5' == r('<?print s.rfind("ur", -4, -1)?>', s=s)
	assert '-1' == r('<?print s.rfind("rk", 2, 3)?>', s=s)
	assert '-1' == r('<?print s.rfind("rk", 7)?>', s=s)
	assert '-1' == r('<?code m = s.rfind?><?print m("rk", 7)?>', s=s)
	l = list("gurkgurk")
	assert '-1' == r('<?print l.rfind("x")?>', l=l)
	assert '6' == r('<?print l.rfind("r")?>', l=l)
	assert '6' == r('<?print l.rfind("r", 2)?>', l=l)
	assert '2' == r('<?print l.rfind("r", 2, 4)?>', l=l)
	assert '6' == r('<?print l.rfind("r", 4, 8)?>', l=l)
	assert '6' == r('<?print l.rfind("r", -3, -1)?>', l=l)
	assert '-1' == r('<?print l.rfind("r", 2, 2)?>', l=l)
	assert '-1' == r('<?print l.rfind("r", 7)?>', l=l)
	assert '7' == r('<?print l.rfind(None)?>', l=[0, None, 1, None, 2, None, 3, None])
	assert '-1' == r('<?code m = l.rfind?><?print m("r", 7)?>', l=l)

	# Make sure that the parameters have the same name in all implementations
	assert '2' == r('<?print s.rfind(sub="rk", start=2, end=4)?>', s=s)


@pytest.mark.ul4
def test_method_day(r):
	assert '12' == r('<?print @(2010-05-12).day()?>')
	assert '12' == r('<?print d.day()?>', d=datetime.date(2010, 5, 12))
	assert '12' == r('<?code m = @(2010-05-12).day?><?print m()?>')


@pytest.mark.ul4
def test_method_month(r):
	assert '5' == r('<?print @(2010-05-12).month()?>')
	assert '5' == r('<?print d.month()?>', d=datetime.date(2010, 5, 12))
	assert '5' == r('<?code m = @(2010-05-12).month?><?print m()?>')


@pytest.mark.ul4
def test_method_year(r):
	assert '5' == r('<?print @(2010-05-12).month()?>')
	assert '5' == r('<?print d.month()?>', d=datetime.date(2010, 5, 12))
	assert '5' == r('<?code m = @(2010-05-12).month?><?print m()?>')


@pytest.mark.ul4
def test_method_hour(r):
	assert '16' == r('<?print @(2010-05-12T16:47:56).hour()?>')
	assert '16' == r('<?print d.hour()?>', d=datetime.datetime(2010, 5, 12, 16, 47, 56))
	assert '16' == r('<?code m = @(2010-05-12T16:47:56).hour?><?print m()?>')


@pytest.mark.ul4
def test_method_minute(r):
	assert '47' == r('<?print @(2010-05-12T16:47:56).minute()?>')
	assert '47' == r('<?print d.minute()?>', d=datetime.datetime(2010, 5, 12, 16, 47, 56))
	assert '47' == r('<?code m = @(2010-05-12T16:47:56).minute?><?print m()?>')


@pytest.mark.ul4
def test_method_second(r):
	assert '56' == r('<?print @(2010-05-12T16:47:56).second()?>')
	assert '56' == r('<?print d.second()?>', d=datetime.datetime(2010, 5, 12, 16, 47, 56))
	assert '56' == r('<?code m = @(2010-05-12T16:47:56).second?><?print m()?>')


@pytest.mark.ul4
def test_method_microsecond(r):
	if r is not render_php:
		assert '123000' == r('<?print @(2010-05-12T16:47:56.123000).microsecond()?>')
		assert '123000' == r('<?print d.microsecond()?>', d=datetime.datetime(2010, 5, 12, 16, 47, 56, 123000))
		assert '123000' == r('<?code m = @(2010-05-12T16:47:56.123000).microsecond?><?print m()?>')


@pytest.mark.ul4
def test_method_weekday(r):
	assert '2' == r('<?print @(2010-05-12).weekday()?>')
	assert '2' == r('<?print d.weekday()?>', d=datetime.date(2010, 5, 12))
	assert '2' == r('<?code m = @(2010-05-12).weekday?><?print m()?>')


@pytest.mark.ul4
def test_method_week(r):
	assert '0' == r('<?print @(2012-01-01).week()?>')
	assert '0' == r('<?print @(2012-01-01).week(0)?>')
	assert '1' == r('<?print @(2012-01-01).week(6)?>')
	assert '1' == r('<?print @(2012-01-02).week()?>')
	assert '1' == r('<?print @(2012-01-02).week(0)?>')
	assert '1' == r('<?print @(2012-01-02).week(6)?>')
	assert '0' == r('<?code m = @(2012-01-01).week?><?print m()?>')

	# Make sure that the parameters have the same name in all implementations
	assert '1' == r('<?print @(2012-01-02).week(firstweekday=0)?>')


@pytest.mark.ul4
def test_method_yearday(r):
	assert '1' == r('<?print @(2010-01-01).yearday()?>')
	assert '366' == r('<?print @(2008-12-31).yearday()?>')
	assert '365' == r('<?print @(2010-12-31).yearday()?>')
	assert '132' == r('<?print @(2010-05-12).yearday()?>')
	assert '132' == r('<?print @(2010-05-12T16:47:56).yearday()?>')
	assert '132' == r('<?print d.yearday()?>', d=datetime.date(2010, 5, 12))
	assert '132' == r('<?print d.yearday()?>', d=datetime.datetime(2010, 5, 12, 16, 47, 56))
	assert '1' == r('<?code m = @(2010-01-01).yearday?><?print m()?>')


@pytest.mark.ul4
def test_method_days(r):
	assert '1' == r('<?print timedelta(1).days()?>')
	assert '1' == r('<?code m = timedelta(1).days?><?print m()?>')


@pytest.mark.ul4
def test_method_seconds(r):
	assert '42' == r('<?print timedelta(0, 42).seconds()?>')
	assert '42' == r('<?code m = timedelta(0, 42).seconds?><?print m()?>')


@pytest.mark.ul4
def test_method_microseconds(r):
	assert '123000' == r('<?print timedelta(0, 0, 123000).microseconds()?>')
	assert '123000' == r('<?code m = timedelta(0, 0, 123000).microseconds?><?print m()?>')


@pytest.mark.ul4
def test_method_months(r):
	assert '17' == r('<?print monthdelta(17).months()?>')
	assert '17' == r('<?code m = monthdelta(17).months?><?print m()?>')


@pytest.mark.ul4
def test_method_append(r):
	assert '[17, 23, 42]' == r('<?code l = [17]?><?code l.append(23, 42)?><?print l?>')
	assert '[17, 23, 42]' == r('<?code l = [17]?><?code m = l.append?><?code m(23, 42)?><?print l?>')


@pytest.mark.ul4
def test_method_insert(r):
	assert '[1, 2, 3, 4]' == r('<?code l = [1,4]?><?code l.insert(1, 2, 3)?><?print l?>')
	assert '[1, 2, 3, 4]' == r('<?code l = [1,4]?><?code m = l.insert?><?code m(1, 2, 3)?><?print l?>')


@pytest.mark.ul4
def test_method_pop(r):
	assert '42;17;23;' == r('<?code l = [17, 23, 42]?><?print l.pop()?>;<?print l.pop(-2)?>;<?print l.pop(0)?>;')
	assert '42;17;23;' == r('<?code l = [17, 23, 42]?><?code m = l.pop?><?print m()?>;<?print m(-2)?>;<?print m(0)?>;')


@pytest.mark.ul4
def test_method_update(r):
	assert '0' == r('<?code d = {}?><?code d.update()?><?print len(d)?>')
	assert '1' == r('<?code d = {}?><?code d.update([["one", 1]])?><?print d.one?>')
	assert '1' == r('<?code d = {}?><?code d.update({"one": 1})?><?print d.one?>')
	assert '1' == r('<?code d = {}?><?code d.update(one=1)?><?print d.one?>')
	assert '1' == r('<?code d = {}?><?code d.update([["one", 0]], {"one": 0}, one=1)?><?print d.one?>')
	assert '1' == r('<?code d = {}?><?code m = d.update?><?code m(one=1)?><?print d.one?>')


@pytest.mark.ul4
def test_method_render(r):
	t = ul4c.Template('<?print prefix?><?print data?><?print suffix?>')

	assert '(f)(o)(o)' == r('<?for c in data?><?code t.render(data=c, prefix="(", suffix=")")?><?end for?>', t=t, data='foo')
	assert '(f)(o)(o)' == r('<?for c in data?><?code t.render(data=c, **{"prefix": "(", "suffix": ")"})?><?end for?>', t=t, data='foo')
	assert '(f)(o)(o)' == r('<?code m = t.render?><?for c in data?><?code m(data=c, prefix="(", suffix=")")?><?end for?>', t=t, data='foo')


@pytest.mark.ul4
def test_def(r):
	assert 'foo' == r('<?def lower?><?print x.lower()?><?end def?><?print lower.renders(x="FOO")?>')


@pytest.mark.ul4
def test_pass_function(r):
	assert "&lt;" == r("<?def x?><?print xe('<')?><?end def?><?code x.render(xe=xmlescape)?>")
	assert "&lt;" == r("<?def xe?><?return xmlescape(s)?><?end def?><?def x?><?print xe(s='<')?><?end def?><?code x.render(xe=xe)?>")
	assert "&lt;" == r("<?def xe?><?return xmlescape(s)?><?end def?><?def x?><?print xe(s='<')?><?end def?><?code x.render()?>")


@pytest.mark.ul4
def test_parse(r):
	assert '42' == r('<?print data.Noner?>', data=dict(Noner=42))


@pytest.mark.ul4
def test_nested_exceptions(r):
	tmpl1 = ul4c.Template("<?print 2*x?>", "tmpl1")
	tmpl2 = ul4c.Template("<?code tmpl1.render(x=x)?>", "tmpl2")
	tmpl3 = ul4c.Template("<?code tmpl2.render(tmpl1=tmpl1, x=x)?>", "tmpl3")

	with raises("unsupported operand type|not supported"):
		r("<?code tmpl3.render(tmpl1=tmpl1, tmpl2=tmpl2, x=x)?>", tmpl1=tmpl1, tmpl2=tmpl2, tmpl3=tmpl3, x=None)


@pytest.mark.ul4
def test_note(r):
	assert "foo" == r("f<?note This is?>o<?note a comment?>o")


@pytest.mark.ul4
def test_templateattributes(r):
	s1 = "<?print x?>"
	t1 = ul4c.Template(s1)

	s2 = "<?printx 42?>"
	t2 = ul4c.Template(s2)

	assert "<?" == r("<?print template.startdelim?>", template=t1)
	assert "?>" == r("<?print template.enddelim?>", template=t1)
	assert s1 == r("<?print template.source?>", template=t1)
	assert "1" == r("<?print len(template.content)?>", template=t1)
	assert "print" == r("<?print template.content[0].type?>", template=t1)
	assert s1 == r("<?print template.content[0].location.tag?>", template=t1)
	assert "x" == r("<?print template.content[0].location.code?>", template=t1)
	assert "var" == r("<?print template.content[0].obj.type?>", template=t1)
	assert "x" == r("<?print template.content[0].obj.name?>", template=t1)
	assert "printx" == r("<?print template.content[0].type?>", template=t2)
	assert "const" == r("<?print template.content[0].obj.type?>", template=t2)
	assert "42" == r("<?print template.content[0].obj.value?>", template=t2)


@pytest.mark.ul4
def test_templateattributes_localtemplate(r):
	# This checks that template attributes work on a closure
	source = "<?def lower?><?print t.lower()?><?end def?>"

	assert source + "<?print lower.source?>" == r(source + "<?print lower.source?>")
	assert source == r(source + "<?print lower.source[lower.location.starttag:lower.endlocation.endtag]?>")
	assert "<?print t.lower()?>" == r(source + "<?print lower.source[lower.location.endtag:lower.endlocation.starttag]?>")
	assert "lower" == r(source + "<?print lower.name?>")


@pytest.mark.ul4
def test_nestedscopes(r):
	# Subtemplates can see the local variables from their parents
	source = """
	<?for i in range(3)?>
		<?def x?>
			<?print i?>!
		<?end def?>
		<?code x.render()?>
	<?end for?>
	"""
	assert "0!1!2!" == r(source, keepws=False)

	# Subtemplates see the state of the variable at the point after the ``<?def?>`` tag,
	# so the following code will use ``i = 1`` instead of ``i = 2`` even if the subtemplate is called after the variable has been changed.
	source = """
	<?code i = 1?>
	<?def x?>
		<?print i?>
	<?end def?>
	<?code i = 2?>
	<?code x.render()?>
	"""
	assert "1" == r(source, keepws=False)


	# Subtemplates see themselves (i.e. the ``TemplateClosure`` object created for them), but no variables defined later
	source = """
	<?def x?>
		<?print type(x)?>;<?print type(y)?>
	<?end def?>
	<?code y = 42?>
	<?code x.render()?>
	"""
	assert "template;undefined" == r(source, keepws=False)

	# This shows the difference between local variables and variables from the parent.
	# ``x`` is passed to the subtemplate, so it will always be the current value instead of the one when it is defined
	# (Furthermore ``y += 1`` will load the variable from the parent but store it as a local variable)
	source = """
	<?def outer?>
		<?def inner?>
			<?code x += 1?>
			<?code y += 1?>
			<?print x?>!
			<?print y?>!
		<?end def?>
		<?code x += 1?>
		<?code y += 1?>
		<?code inner.render(x=x)?>
		<?print x?>!
		<?print y?>!
	<?end def?>
	<?code x += 1?>
	<?code y += 1?>
	<?code outer.render(x=x)?>
	<?print x?>!
	<?print y?>!
	"""

	assert "45!43!44!43!43!43!" == r(source, keepws=False, x=42, y=42)


def universaltemplate(keepws=True):
	return ul4c.Template("""
		text
		<?code x = 'gurk'?>
		<?code x = 42?>
		<?code x = 4.2?>
		<?code x = Undefined?>
		<?code x = ReallyUndefined?>
		<?code x = None?>
		<?code x = False?>
		<?code x = True?>
		<?code x = @(2009-01-04)?>
		<?code x = #0063a8?>
		<?code x = [42]?>
		<?code x = {"fortytwo": 42}?>
		<?code x = [x for x in range(10) if i % 2]?>
		<?code x = {x : x*x for x in range(10) if i % 2}?>
		<?code x = (x for x in range(10) if i % 2)?>
		<?code x = y?>
		<?code x += 42?>
		<?code x -= 42?>
		<?code x *= 42?>
		<?code x /= 42?>
		<?code x //= 42?>
		<?code x %= 42?>
		<?print x.gurk?>
		<?print x["gurk"]?>
		<?print x[1:2]?>
		<?print x[1:]?>
		<?print x[:2]?>
		<?print x[:]?>
		<?printx x?>
		<?for x in "12"?><?print x?><?break?><?continue?><?end for?>
		<?print not x?>
		<?print -x?>
		<?print x in y?>
		<?print x not in y?>
		<?print x==y?>
		<?print x!=y?>
		<?print x<y?>
		<?print x<=y?>
		<?print x>y?>
		<?print x>=y?>
		<?print x+y?>
		<?print x*y?>
		<?print x/y?>
		<?print x//y?>
		<?print x and y?>
		<?print x or y?>
		<?print x % y?>
		<?print now()?>
		<?print repr(1)?>
		<?print range(1, 2)?>
		<?print range(1, 2, 3)?>
		<?print rgb(1, 2, 3, 4)?>
		<?print repr(1, 2, x=17, y=23, *args, **kwargs)?>
		<?print x.r()?>
		<?print x.find(1)?>
		<?print x.find(1, 2)?>
		<?print x.find(1, 2, 3)?>
		<?print x.find(1, 2, x=17, y=23, *args, **kwargs)?>
		<?if x?>gurk<?elif y?>hurz<?else?>hinz<?end if?>
		<?code x.render(a=1, b=2)?>
		<?def x?>foo<?end def?>
		<?def x?><?return x?><?end def?>
		<?code x.render()?>
	""")


@pytest.mark.ul4
def test_strtemplate():
	t1 = universaltemplate(True)
	str(t1)

	t2 = universaltemplate(False)
	str(t2)


@pytest.mark.ul4
def test_keepws():
	s = """
		<?for i in range(10)?>
			<?print i?>
			;
		<?end for?>
	"""
	t = ul4c.Template(s, keepws=True)
	output1 = t.renders()
	t.keepws = False
	output2 = t.renders()
	assert output1 != output2
	assert "".join(output1.split()) == output2


@pytest.mark.ul4
def test_keepws_initialws(r):
	assert " foo" == r("<?if True?> foo<?end if?>", keepws=False)
	assert " foobar" == r("<?if True?> foo\n \tbar<?end if?>", keepws=False)


@pytest.mark.ul4
def test_keepws_nested(r):
	s1 = "<?def nested1?>1n\n<?code second.render()?><?end def?>1\n<?code nested1.render(second=second)?>"
	s2 = "<?def nested2?>2n\n<?end def?>2\n<?code nested2.render()?>"

	assert "1\n1n\n22n" == r(s1, keepws=True, second=ul4c.Template(s2, keepws=False))
	assert "11n2\n2n\n" == r(s1, keepws=False, second=ul4c.Template(s2, keepws=True))


@pytest.mark.ul4
def test_function(c):
	assert 42 == c("<?return 42?>")


@pytest.mark.ul4
def test_function_value(c):
	assert 84 == c("<?return 2*x?>", x=42)


@pytest.mark.ul4
def test_function_multiple_returnvalues(c):
	assert 84 == c("<?return 2*x?><?return 3*x?>", x=42)


@pytest.mark.ul4
def test_function_name(c):
	assert "f" == c("<?def f?><?return f.name?><?end def?><?return f(f=f)?>")


@pytest.mark.ul4
def test_function_closure(c):
	assert 24 == c("<?code y=3?><?def inner?><?return 2*x*y?><?end def?><?return inner(x=4)?>")
	assert 24 == c("<?def outer?><?code y=3?><?def inner?><?return 2*x*y?><?end def?><?return inner?><?end def?><?return outer()(x=4)?>")


@pytest.mark.ul4
def test_return_in_template(r):
	assert "gurk" == r("gurk<?return 42?>hurz")


@pytest.mark.ul4
def test_customattributes():
	class CustomAttributes:
		ul4attrs = {"foo", "+bar"}
		def __init__(self, foo, bar):
			self.foo = foo
			self.bar = bar

	o = CustomAttributes(foo=42, bar=23)
	assert "42" == render_python("<?print o.foo?>", o=o)
	assert "23" == render_python("<?print o.bar?>", o=o)
	assert "undefined" == render_python("<?print type(o.baz)?>", o=o)
	assert "42" == render_python("<?print o['foo']?>", o=o)
	assert "23" == render_python("<?print o['bar']?>", o=o)
	assert "undefined" == render_python("<?print type(o['baz'])?>", o=o)
	assert "True" == render_python("<?print 'foo' in o?>", o=o)
	assert "True" == render_python("<?print 'bar' in o?>", o=o)
	assert "False" == render_python("<?print 'baz' in o?>", o=o)
	assert "[['bar', 23], ['foo', 42]]" == render_python("<?print repr(sorted(list(o.items())))?>", o=o)
	assert "[23, 42]" == render_python("<?print repr(sorted(list(o.values())))?>", o=o)
	assert "foo" == render_python("<?for attr in o?><?if attr == 'foo'?><?print attr?><?end if?><?end for?>", o=o)
	assert "bar" == render_python("<?for attr in o?><?if attr == 'bar'?><?print attr?><?end if?><?end for?>", o=o)

	o = CustomAttributes(foo=42, bar=23)
	with raises("readonly"):
		render_python("<?code o.foo = 43?><?print o.foo?>", o=o)
	with raises("readonly"):
		render_python("<?code o['foo'] = 43?><?print o.foo?>", o=o)
	assert "17" == render_python("<?code o.bar = 17?><?print o.bar?>", o=o)
	assert "17" == render_python("<?code o['bar'] = 17?><?print o.bar?>", o=o)

	o = CustomAttributes(foo=42, bar=23)
	with raises("readonly"):
		render_python("<?code o.foo += 1?><?print o.foo?>", o=o)
	with raises("readonly"):
		render_python("<?code o['foo'] += 1?><?print o.foo?>", o=o)
	assert "24" == render_python("<?code o.bar += 1?><?print o.bar?>", o=o)
	assert "25" == render_python("<?code o['bar'] += 1?><?print o.bar?>", o=o)

	o = CustomAttributes(foo=42, bar=23)
	with raises("readonly"):
		render_python("<?code o.foo -= 1?><?print o.foo?>", o=o)
	with raises("readonly"):
		render_python("<?code o['foo'] -= 1?><?print o.foo?>", o=o)
	assert "22" == render_python("<?code o.bar -= 1?><?print o.bar?>", o=o)
	assert "21" == render_python("<?code o['bar'] -= 1?><?print o.bar?>", o=o)

	o = CustomAttributes(foo=42, bar=23)
	with raises("readonly"):
		render_python("<?code o.foo *= 2?><?print o.foo?>", o=o)
	with raises("readonly"):
		render_python("<?code o['foo'] *= 2?><?print o.foo?>", o=o)
	assert "46" == render_python("<?code o.bar *= 2?><?print o.bar?>", o=o)
	assert "92" == render_python("<?code o['bar'] *= 2?><?print o.bar?>", o=o)

	o = CustomAttributes(foo=42, bar=23)
	with raises("readonly"):
		render_python("<?code o.foo //= 2?><?print o.foo?>", o=o)
	with raises("readonly"):
		render_python("<?code o['foo'] //= 2?><?print o.foo?>", o=o)
	assert "11" == render_python("<?code o.bar //= 2?><?print o.bar?>", o=o)
	assert "5" == render_python("<?code o['bar'] //= 2?><?print o.bar?>", o=o)

	o = CustomAttributes(foo=42, bar=23)
	with raises("readonly"):
		render_python("<?code o.foo /= 2?><?print o.foo?>", o=o)
	with raises("readonly"):
		render_python("<?code o['foo'] /= 2?><?print o.foo?>", o=o)
	assert "11.5" == render_python("<?code o.bar /= 2?><?print o.bar?>", o=o)
	assert "5.75" == render_python("<?code o['bar'] /= 2?><?print o.bar?>", o=o)

	o = CustomAttributes(foo=42, bar=23)
	with raises("readonly"):
		render_python("<?code o.foo %= 2?><?print o.foo?>", o=o)
	with raises("readonly"):
		render_python("<?code o['foo'] %= 2?><?print o.foo?>", o=o)
	assert "3" == render_python("<?code o.bar %= 10?><?print o.bar?>", o=o)
	assert "1" == render_python("<?code o['bar'] %= 2?><?print o.bar?>", o=o)


@pytest.mark.ul4
def test_custommethods():
	class CustomMethod:
		ul4attrs = {"foo", "bar"}

		def foo(self):
			return 42

		@ul4c.generator
		def bar(self):
			yield "gurk"
			yield "hurz"
			return 42

		def baz(self):
			pass

	o = CustomMethod()
	assert "42" == render_python("<?print o.foo()?>", o=o)
	assert "gurkhurz42" == render_python("<?print o.bar()?>", o=o)
	with raises("baz"):
		render_python("<?print o.baz()?>", o=o)


@pytest.mark.ul4
def test_setlvalue(r):
	assert "bar" == r("<?code d = {}?><?code d.foo = 'bar'?><?print d.foo?>")
	assert "bar" == r("<?code d = {}?><?code d['foo'] = 'bar'?><?print d['foo']?>")
	assert "bar" == r("<?code d = ['bar']?><?code d[0] = 'bar'?><?print d[0]?>")
	assert "baz" == r("<?code d = {'foo': {}}?><?code d.foo.bar = 'baz'?><?print d.foo.bar?>")
	assert "baz" == r("<?code d = {'foo': {}}?><?code d.foo['bar'] = 'baz'?><?print d.foo['bar']?>")
	assert "baz" == r("<?code d = {'foo': ['bar']}?><?code d.foo[0] = 'baz'?><?print d.foo[0]?>")
	assert "baz" == r("<?code d = ['bar']?><?def f?><?return d?><?end def?><?code f()[0] = 'baz'?><?print d[0]?>")


@pytest.mark.ul4
def test_addlvalue(r):
	assert "barbaz" == r("<?code d = {'foo': 'bar'}?><?code d.foo += 'baz'?><?print d.foo?>")
	assert "barbaz" == r("<?code d = {'foo': 'bar'}?><?code d['foo'] += 'baz'?><?print d['foo']?>")
	assert "barbaz" == r("<?code d = ['bar']?><?code d[0] += 'baz'?><?print d[0]?>")
	assert "barbaz" == r("<?code d = {'foo': {'bar' : 'bar'}}?><?code d.foo.bar += 'baz'?><?print d.foo.bar?>")
	assert "barbaz" == r("<?code d = {'foo': {'bar' : 'bar'}}?><?code d.foo['bar'] += 'baz'?><?print d.foo['bar']?>")
	assert "barbaz" == r("<?code d = {'foo': ['bar']}?><?code d.foo[0] += 'baz'?><?print d.foo[0]?>")
	assert "barbaz" == r("<?code d = ['bar']?><?def f?><?return d?><?end def?><?code f()[0] += 'baz'?><?print d[0]?>")
	assert "[1, 2, 3, 4][1, 2, 3, 4]" == r("<?code d = {'foo': [1, 2]}?><?code l = d.foo?><?code d.foo += [3, 4]?><?print d.foo?><?print l?>")


@pytest.mark.ul4
def test_sublvalue(r):
	assert "6" == r("<?code d = {'foo': 23}?><?code d.foo -= 17?><?print d.foo?>")
	assert "6" == r("<?code d = {'foo': 23}?><?code d['foo'] -= 17?><?print d['foo']?>")
	assert "6" == r("<?code d = [23]?><?code d[0] -= 17?><?print d[0]?>")
	assert "6" == r("<?code d = {'foo': {'bar' : 23}}?><?code d.foo.bar -= 17?><?print d.foo.bar?>")
	assert "6" == r("<?code d = {'foo': {'bar' : 23}}?><?code d.foo['bar'] -= 17?><?print d.foo['bar']?>")
	assert "6" == r("<?code d = {'foo': [23]}?><?code d.foo[0] -= 17?><?print d.foo[0]?>")
	assert "6" == r("<?code d = [23]?><?def f?><?return d?><?end def?><?code f()[0] -= 17?><?print d[0]?>")


@pytest.mark.ul4
def test_mullvalue(r):
	assert "42" == r("<?code d = {'foo': 6}?><?code d.foo *= 7?><?print d.foo?>")
	assert "42" == r("<?code d = {'foo': 6}?><?code d['foo'] *= 7?><?print d['foo']?>")
	assert "42" == r("<?code d = [6]?><?code d[0] *= 7?><?print d[0]?>")
	assert "42" == r("<?code d = {'foo': {'bar' : 6}}?><?code d.foo.bar *= 7?><?print d.foo.bar?>")
	assert "42" == r("<?code d = {'foo': {'bar' : 6}}?><?code d.foo['bar'] *= 7?><?print d.foo['bar']?>")
	assert "42" == r("<?code d = {'foo': [6]}?><?code d.foo[0] *= 7?><?print d.foo[0]?>")
	assert "42" == r("<?code d = [6]?><?def f?><?return d?><?end def?><?code f()[0] *= 7?><?print d[0]?>")
	assert "[1, 2, 1, 2][1, 2, 1, 2]" == r("<?code d = {'foo': [1, 2]}?><?code l = d.foo?><?code d.foo *= 2?><?print d.foo?><?print l?>")


@pytest.mark.ul4
def test_floordivlvalue(r):
	assert "2" == r("<?code d = {'foo': 5}?><?code d.foo //= 2?><?print d.foo?>")
	assert "2" == r("<?code d = {'foo': 5}?><?code d['foo'] //= 2?><?print d['foo']?>")
	assert "2" == r("<?code d = [5]?><?code d[0] //= 2?><?print d[0]?>")
	assert "2" == r("<?code d = {'foo': {'bar' : 5}}?><?code d.foo.bar //= 2?><?print d.foo.bar?>")
	assert "2" == r("<?code d = {'foo': {'bar' : 5}}?><?code d.foo['bar'] //= 2?><?print d.foo['bar']?>")
	assert "2" == r("<?code d = {'foo': [5]}?><?code d.foo[0] //= 2?><?print d.foo[0]?>")
	assert "2" == r("<?code d = [5]?><?def f?><?return d?><?end def?><?code f()[0] //= 2?><?print d[0]?>")


@pytest.mark.ul4
def test_truedivlvalue(r):
	assert "2.5" == r("<?code d = {'foo': 5}?><?code d.foo /= 2?><?print d.foo?>")
	assert "2.5" == r("<?code d = {'foo': 5}?><?code d['foo'] /= 2?><?print d['foo']?>")
	assert "2.5" == r("<?code d = [5]?><?code d[0] /= 2?><?print d[0]?>")
	assert "2.5" == r("<?code d = {'foo': {'bar' : 5}}?><?code d.foo.bar /= 2?><?print d.foo.bar?>")
	assert "2.5" == r("<?code d = {'foo': {'bar' : 5}}?><?code d.foo['bar'] /= 2?><?print d.foo['bar']?>")
	assert "2.5" == r("<?code d = {'foo': [5]}?><?code d.foo[0] /= 2?><?print d.foo[0]?>")
	assert "2.5" == r("<?code d = [5]?><?def f?><?return d?><?end def?><?code f()[0] /= 2?><?print d[0]?>")


@pytest.mark.ul4
def test_truedivlvalue(r):
	assert "1" == r("<?code d = {'foo': 5}?><?code d.foo %= 2?><?print d.foo?>")
	assert "1" == r("<?code d = {'foo': 5}?><?code d['foo'] %= 2?><?print d['foo']?>")
	assert "1" == r("<?code d = [5]?><?code d[0] %= 2?><?print d[0]?>")
	assert "1" == r("<?code d = {'foo': {'bar' : 5}}?><?code d.foo.bar %= 2?><?print d.foo.bar?>")
	assert "1" == r("<?code d = {'foo': {'bar' : 5}}?><?code d.foo['bar'] %= 2?><?print d.foo['bar']?>")
	assert "1" == r("<?code d = {'foo': [5]}?><?code d.foo[0] %= 2?><?print d.foo[0]?>")
	assert "1" == r("<?code d = [5]?><?def f?><?return d?><?end def?><?code f()[0] %= 2?><?print d[0]?>")


@pytest.mark.ul4
def test_endless_recursion(r):
	with raises("maximum recursion depth exceeded|Maximum call stack size exceeded|StackOverflowError"):
		r("""
			<?def f?>
				<?for child in container?>
					<?code f(f=f, container=container)?>
				<?end for?>
			<?end def?>
			<?code x = []?>
			<?code x.append(x)?><?code f(f=f, container=x)?>
		""")


@pytest.mark.ul4
def test_jssource():
	t = universaltemplate()
	t.jssource()


@pytest.mark.ul4
def test_javasource():
	t = universaltemplate()
	t.javasource()


@pytest.mark.ul4
def test_attr_if(r):
	cond = ul4.attr_if(html.a("gu'\"rk"), cond="cond")

	s = html.div(class_=cond).conv().string()
	assert '<div></div>' == r(s, cond=False)
	assert '''<div class="gu'&quot;rk"></div>''' == r(s, cond=True)

	s = html.div(class_=(cond, "hurz")).conv().string()
	assert '<div class="hurz"></div>' == r(s, cond=False)
	assert '''<div class="gu'&quot;rkhurz"></div>''' == r(s, cond=True)

	s = cond.conv().string()
	assert '' == r(s, cond=False)
	assert '''<a>gu'"rk</a>''' == r(s, cond=True)

	s = html.ul(compact=ul4.attr_if(True, cond="cond")).conv().string()
	assert '<ul></ul>' == r(s, cond=False)
	assert '''<ul compact="compact"></ul>''' == r(s, cond=True)
