summaryrefslogtreecommitdiff
path: root/devel-utf8/tests
diff options
context:
space:
mode:
authorNathan Gass2012-03-22 18:18:42 +0000
committerNathan Gass2012-03-22 18:18:42 +0000
commitd59a4921188753dbe4c0161081755a28112c3ef6 (patch)
tree81496414d988f37f1db9d92c9750d888ffa13746 /devel-utf8/tests
parentca11771e8fad5fef96615df4c44e04b8fb60ac31 (diff)
downloaditools-d59a4921188753dbe4c0161081755a28112c3ef6.tar.gz
itools-d59a4921188753dbe4c0161081755a28112c3ef6.tar.bz2
itools-d59a4921188753dbe4c0161081755a28112c3ef6.zip
Branch itools/devel-utf8 created
Diffstat (limited to 'devel-utf8/tests')
-rwxr-xr-xdevel-utf8/tests/autoprepend.t38
-rwxr-xr-xdevel-utf8/tests/exec.t23
-rwxr-xr-xdevel-utf8/tests/getopt.t29
-rwxr-xr-xdevel-utf8/tests/it.t285
-rwxr-xr-xdevel-utf8/tests/it_dbi.t254
-rwxr-xr-xdevel-utf8/tests/it_html.t159
-rwxr-xr-xdevel-utf8/tests/it_text.t18
-rwxr-xr-xdevel-utf8/tests/it_url.t135
-rwxr-xr-xdevel-utf8/tests/it_xml.t120
-rwxr-xr-xdevel-utf8/tests/itjs.t50
10 files changed, 1111 insertions, 0 deletions
diff --git a/devel-utf8/tests/autoprepend.t b/devel-utf8/tests/autoprepend.t
new file mode 100755
index 0000000..bf40605
--- /dev/null
+++ b/devel-utf8/tests/autoprepend.t
@@ -0,0 +1,38 @@
+#!/www/server/bin/php -qC
+<?php
+
+it_text::init();
+$GLOBALS['it_text']->statictext = array(
+ '_' => array("de" => "Deutsch", "en" => "English"),
+ 'foo' => array("de" => "bar {v1}", "en" => "qux {v1}"),
+);
+
+is(
+ T('foo'),
+ "bar {v1}",
+ "simple T()"
+);
+
+is(
+ T('foo', 'en'),
+ "qux {v1}",
+ "simple T() with language"
+);
+
+is(
+ T('foo', array('v1' => "gna<bber")),
+ "bar gna&lt;bber",
+ "T() with quoted values"
+);
+
+is(
+ T('foo', array('v1' => "gna<bber"), 'en'),
+ "qux gna&lt;bber",
+ "T() with with quoted values and language"
+);
+
+is(
+ T('foo', 'en', array('v1' => "gna<bber")),
+ "qux gna&lt;bber",
+ "T() with with language and quoted values"
+);
diff --git a/devel-utf8/tests/exec.t b/devel-utf8/tests/exec.t
new file mode 100755
index 0000000..689bd26
--- /dev/null
+++ b/devel-utf8/tests/exec.t
@@ -0,0 +1,23 @@
+#!/www/server/bin/php -qC
+<?php
+
+# Tests for getopt in it.class
+
+is(it::exec("echo gna"), "gna\n", "basic exec");
+is(it::exec("echo {arg}", array('arg' => 'gna')), "gna\n", "exec with argument");
+is(it::shell_command("echo {arg}", array('arg' => 'gna07,-:blah')), "echo gna07,-:blah", "don't quote arguments with only whitelistes characters");
+is(it::shell_command("echo {arg}", array('arg' => '2>&1')), "echo '2>&1'", "quote arguments with dangerous characters");
+is(it::shell_command("echo {arg}", array('arg' => '')), "echo ''", "quote empty arguments");
+
+foreach (array("", "C", "de_CH", "de_CH.utf8") as $locale) {
+ setlocale(LC_ALL, $locale);
+ $arg = "preüpost";
+ if (it::match('utf8', $locale))
+ $arg = utf8_encode($arg);
+ is(it::exec("echo " . $arg), $arg . "\n", "exec with umlaut (locale '$locale')");
+ is(it::exec("echo {arg}", array('arg' => $arg)), $arg . "\n", "exec with argument and umlaut (locale '$locale')");
+}
+
+is(it::_exec_quotevalue(""), "''", "empty arg needs quotes");
+is(it::_exec_quotevalue("*"), "'*'", "special chars need quotes");
+is(it::_exec_quotevalue("Aabcdef0123456789"), "Aabcdef0123456789", "simple case. tel:debug_getdata needs unquoted vals");
diff --git a/devel-utf8/tests/getopt.t b/devel-utf8/tests/getopt.t
new file mode 100755
index 0000000..7a84588
--- /dev/null
+++ b/devel-utf8/tests/getopt.t
@@ -0,0 +1,29 @@
+#!/www/server/bin/php -qC
+<?php
+
+# Tests for getopt in it.class
+
+$GLOBALS['usage'] = "Usage: doesnotexist.php [OPTIONS]
+Some help to a not existing program
+ -h,--help the help argument
+ -a,--argument=ARG the arg argument
+ -0,--zero testworthy shortarg
+";
+
+function getopt_ok($argv, $exp, $name)
+{
+ $_SERVER['argv'] = array_merge(array('doesnotexist.php'), $argv);
+ $got = it::getopt($GLOBALS['usage']);
+ return is($got['argument'], $exp, $name);
+}
+
+foreach (array("" => "blah gnaber", " (umlaute)" => "pre üäpost") as $variant => $testarg) {
+ getopt_ok(array('-a', $testarg), $testarg, "Short version" . $variant);
+ getopt_ok(array('--argument', $testarg), $testarg, "Long version with space" . $variant);
+ getopt_ok(array("--argument=$testarg"), $testarg, "Long version with equal" . $variant);
+}
+
+$_SERVER['argv'] = array('doesnotexist.php', '-0');
+$zero_opts = it::getopt($GLOBALS['usage']);
+ok($zero_opts['zero'], '-0');
+
diff --git a/devel-utf8/tests/it.t b/devel-utf8/tests/it.t
new file mode 100755
index 0000000..1a308ec
--- /dev/null
+++ b/devel-utf8/tests/it.t
@@ -0,0 +1,285 @@
+#!/www/server/bin/php -qC
+<?php
+
+# Tests for it.class
+
+function match($regex, $string, $expect, $name)
+{
+ $GLOBALS['TEST_MORE_LEVEL'] = 1;
+ $pass = is (it::match($regex, $string), $expect, $name);
+ if (!$pass) {
+ diag(" regex given: $regex");
+ diag(" regex converted: " . it::convertregex($regex));
+ }
+ $GLOBALS['TEST_MORE_LEVEL'] = 0;
+}
+
+match(
+ 'b', 'aaaabaaaa',
+ 'b',
+ 'simple regex'
+ );
+match(
+ 'a/b', ' a/b ',
+ 'a/b',
+ 'regex with /'
+);
+match(
+ 'aa(bb)aa(cc)aa(dd)qq', 'aabbaaccaaddqq',
+ array( 'bb', 'cc', 'dd' ),
+ 'return array of captures'
+ );
+match(
+ '\bblah\b', ' blah ',
+ 'blah',
+ 'match \b at spaces'
+ );
+match(
+ '\bblah\b', 'blah',
+ 'blah',
+ 'match \b at end of string'
+ );
+match(
+ '\bblah\b', 'ablahc',
+ false,
+ 'don\'t match \b at word chars'
+ );
+match(
+ '\bblah\b', 'Üblahä',
+ false,
+ 'don\'t match \b at umlaute in latin1'
+ );
+match(
+ '\Bblah\B', ' blah ',
+ false,
+ 'don\'t match \B at spaces'
+ );
+match(
+ '\Bblah\B', 'blah',
+ false,
+ 'don\'t match \B at end of string'
+ );
+match(
+ '\Bblah\B', 'ablahc',
+ 'blah',
+ 'match \B at word chars'
+ );
+match(
+ '\Bblah\B', 'Üblahä',
+ 'blah',
+ 'match \B at umlaute in latin1'
+ );
+match(
+ '\w+', ' |#Üblahä ',
+ 'Üblahä',
+ 'include umlaute in \w'
+ );
+match(
+ '[[:alpha:]]+', ' |#blahä ',
+ 'blahä',
+ 'include umlaute in [[:alpha:]]'
+ );
+match(
+ '\W+', ' |#Üblahä ',
+ ' |#',
+ 'don\'t include umlaute in \W'
+ );
+match(
+ '\ba', 'äa',
+ '',
+ '\b must know umlauts'
+ );
+
+eval( '$escapedwordregex = "' . it::convertregex( '\w' ) . '";' );
+$escapedwordregex = preg_replace( '|[\\\\/]|', '', $escapedwordregex );
+
+match(
+ '\\\\w+', $escapedwordregex,
+ false,
+ 'don\'t parse \w in \\\\w at beginning (no match)'
+ );
+match(
+ 'aaa\\\\w+', ' aaa\www ',
+ 'aaa\www',
+ 'don\'t parse \w in \\\\w at beginning (match)'
+ );
+match(
+ 'aaa\\\\w+', 'aaa' . $escapedwordregex,
+ false,
+ 'don\'t parse \w in \\\\w after chars (no match)'
+ );
+match(
+ 'aaa\\\\w+', ' aaa\www ',
+ 'aaa\www',
+ 'don\'t parse \w in \\\\w after chars (match)'
+ );
+match(
+ '\\\\\\\\w+', '\\' . $escapedwordregex,
+ false,
+ 'don\'t parse \w in \\\\\\\w (no match)'
+ );
+match(
+ '\\\\\\\\w+', ' \\\\www ',
+ '\\\\www',
+ 'don\'t parse \\\\\\\\w as \w (match)'
+ );
+match(
+ '[\w]+', '[[[]]]---',
+ false,
+ 'replace \w in [\w] correctly (no match)'
+ );
+match(
+ '[\w]+', ' \\\\aword[[[]]] ',
+ 'aword',
+ 'replace \w in [\w] correctly (match)'
+ );
+match(
+ '[\\\\w]+', ' blabergna ',
+ false,
+ 'don\'t parse \w in [\\\\w] (no match)'
+ );
+match(
+ '[\\\\w]+', ' \\\\worda[[[]',
+ '\\\\w',
+ 'don\'t parse \w in [\\\\w] (match)'
+ );
+match(
+ '[a\W]+', 'bbbbbbb a a%$+ accccc',
+ ' a a%$+ a',
+ '\W in []'
+ );
+match(
+ '\\\\\\w+', ' \Üblahä ',
+ '\Üblahä',
+ 'parse \w in \\\\\\w at beginning'
+ );
+match(
+ 'aaa\\\\\\w+', ' aaa\Üblahä ',
+ 'aaa\Üblahä',
+ 'parse \w in \\\\\\w after chars'
+ );
+is(
+ it::replace(
+ array(
+ 'regex1' => 'repl1',
+ 'regex2' => 'repl2',
+ 'regex3' => 'repl3' ),
+ 'regex2 regex1 regex3' ),
+ 'repl2 repl1 repl3',
+ 'test tr regex function'
+ );
+is(
+ it::match( '\w+', 'word1 wörd2 word_3', array('all' => true )),
+ array( 'word1', 'wörd2', 'word_3' ),
+ "test match_all function"
+ );
+match(
+ 'aBcD', ' aBcD ',
+ 'aBcD',
+ "caseinsensitive is default"
+ );
+match(
+ 'ö', 'Ö',
+ 'Ö',
+ 'match umlaute in latin1 case insensitive'
+ );
+
+is(
+ it::match(utf8_encode('aöBÜ'), utf8_encode("AÖbü"), array('utf8' => true)),
+ utf8_encode('AÖbü'),
+ "match utf-8 umlaute in case insensitive"
+);
+
+$oldcharset = ini_get('default_charset');
+ini_set('default_charset', 'utf-8');
+match(
+ utf8_encode('aöBÜ'), utf8_encode('AÖbü'),
+ utf8_encode('AÖbü'),
+ "match utf-8 umlaute in case insensitive using default_charset"
+);
+is(
+ it::match('aöBÜ', 'AÖbü', array('utf8' => false)),
+ 'AÖbü',
+ "non-utf-8 override with default_charset=utf-8"
+);
+match(
+ '\w+', utf8_encode('Müller'),
+ utf8_encode('Müller'),
+ '\w matches umlaut in utf-8 mode'
+);
+match(
+ 'M.ller', utf8_encode('Müller'),
+ utf8_encode('Müller'),
+ '. matches umlaut in utf-8 mode'
+);
+ini_set('default_charset', $oldcharset);
+
+is(
+ it::match( 'abc', "aBc", array('casesensitive' => 1 )),
+ false,
+ "set case sensitivity by parameter"
+ );
+
+is(
+ it::match( '\w+', 'word1 wörd2 word_3', array('all' => 1 )),
+ array( 'word1', 'wörd2', 'word_3' ),
+ "test all=>1 without captures"
+ );
+is(
+ it::match( '\w+\s+(\d+)', 'word1 12 wörd2 3 word_3 4', array('all' => 1 )),
+ array( '12', '3', '4' ),
+ "test all=>1 with one capture"
+ );
+is(
+ it::match( '(\w+)\s+(\d+)', 'word1 12 wörd2 3 word_3 4', array('all' => 1 )),
+ array( array( 'word1', '12' ), array( 'wörd2', '3' ), array( 'word_3', '4' ) ),
+ "test all=>1 with captures"
+ );
+is(
+ it::match( '(\w+)\s+(\d+)', 'word1 12 wörd2 3 word_3 4', array('all' => 1, 'pattern_order' => 1 )),
+ array( array( 'word1', 'wörd2', 'word_3' ), array( '12', '3', '4' ) ),
+ "test all=>1,pattern_order=>1"
+ );
+
+is(it::replace(array('a' => "1", 'b' => "2"), "ab"), "12");
+is(it::replace(array('!' => "x"), "!"), "x");
+is(it::replace(array('\w' => "x"), "oö"), "xx");
+is(it::replace(array('[[:alpha:]]' => "x"), "ö"), "x");
+is(it::replace(array('\w' => "x", '#' => "!"), "#ö"), "!x");
+is(it::replace(array('#' => "!", '\w' => "x"), "#ö"), "!x");
+is(it::replace(array('ö' => "x"), "Ö"), "x");
+is(it::replace(array('a' => "1"), "aaa", array('limit' => 1)), "1aa");
+
+# it::filter_keys tests
+
+$data = array('a' => 1, 'b' => 2, 'c' => 3);
+is(it::filter_keys($data, 'a'), array('a' => 1), "select one key");
+is(it::filter_keys($data, array('a', 'b')), array('a' => 1, 'b' => 2), "select two keys with array");
+is(it::filter_keys($data, 'a,b'), array('a' => 1, 'b' => 2), "select two keys with string");
+is(
+ array_keys(it::filter_keys($data, 'b,a')),
+ array('a', 'b'),
+ "keep order of data array per default");
+is(
+ array_keys(it::filter_keys($data, 'b,a', array('reorder' => true))),
+ array('b', 'a'),
+ "reorder with given key order");
+
+# it::date tests
+
+is(it::date('date', '2011-10-25'), '25.10.2011', 'parse date string with strtotime');
+is(it::date('date', '2011-10-25 + 3 days'), '28.10.2011', 'some date arithmetic');
+is(it::date('datetime', time()), it::date('datetime'), 'recognize int as timestamp');
+is(it::date('datetime', time()*1.0), it::date('datetime'), 'recognize float as timestamp');
+is(it::date('datetime', time() . ''), it::date('datetime'), 'recognize digit string as timestamp');
+is(it::date('datetime', '@' . time()), it::date('datetime'), 'recognize strtotime timestamp format');
+is(it::date('datetime', 10), it::date('datetime', "10"), 'numeric and string give same result');
+is(it::date('datetime', 10.0), it::date('datetime', "10"), '... as long as num is properly truncated');
+is(it::date('datetime', 10.5), it::date('datetime', "10"), '... with one digit after point');
+is(it::date('datetime', 10.56), it::date('datetime', "10"), '... with two digits after point');
+is(it::date('datetime', 1000000), it::date('datetime', "1000000"), '... large nummer');
+is(it::date('datetime', 1000000.543), it::date('datetime', "1000000"), '... large nummer and point');
+is(it::date('time', "10.5"), "10:05", 'interpret string with points with strtotime');
+is(it::date('time', "10.05"), "10:05", 'interpret string with points with strtotime');
+
+?>
diff --git a/devel-utf8/tests/it_dbi.t b/devel-utf8/tests/it_dbi.t
new file mode 100755
index 0000000..4a58188
--- /dev/null
+++ b/devel-utf8/tests/it_dbi.t
@@ -0,0 +1,254 @@
+#!/www/server/bin/php -qC
+<?php
+
+# Tests for it_dbi.class
+
+# Initialize DB
+$db = array('db' => "lib_search_ch", 'safety' => 0);
+$dbi = new it_dbi($db);
+$dbi->query('create temporary table it_dbi_test (
+ ID int not null auto_increment,
+ x int,
+ foo varchar(42),
+ primary key(ID)
+);');
+
+$record = new it_dbi($db + array('table' => "it_dbi_test"));
+
+$record->insert(array('x' => 42, 'foo' => null));
+$record->insert(array('foo' => "bar"));
+$record->insert(array('x' => 64738, 'foo' => "q'uux"));
+
+is(
+ $record->ID,
+ 3,
+ "auto_increment"
+);
+
+$record->read(1);
+is(
+ array($record->_key, $record->x, $record->foo),
+ array(1, 42, null),
+ "read"
+);
+
+is(
+ $record->select(),
+ 3,
+ "select without parameters select all"
+);
+
+is(
+ $record->select(array('foo <>' => ""), "LIMIT 1"),
+ 1,
+ "select with multiple parameters (LIMIT part)"
+);
+is(
+ $record->foo,
+ "bar",
+ "select with multiple parameters (foo part)"
+);
+is(
+ $record->select(array('ID IN' => array(2,3))),
+ 2,
+ "select with IN"
+);
+is(
+ $record->select(array('ID NI' => array(2,3))),
+ 2,
+ "select with NI"
+);
+is(
+ $record->select(array('ID NOT IN' => array(2,3))),
+ 1,
+ "select with NOT IN"
+);
+is(
+ $record->select(array('ID IN' => array())),
+ 0,
+ "select with empty IN"
+);
+is(
+ $record->select(array('ID NOT IN' => array())),
+ 3,
+ "select with empty NOT IN"
+);
+
+it_dbi::createclass(array('table' => "it_dbi_test", 'forcecreate' => true));
+
+$record = new it_dbi_test;
+is(
+ $record->x,
+ null,
+ "constructor of created class without argument"
+);
+
+$record = new it_dbi_test(2);
+is(
+ $record->ID,
+ 2,
+ "constructor of created class with id parameter"
+);
+
+$record = new it_dbi_test(array('x >' => 0), "ORDER BY x DESC");
+is(
+ $record->x,
+ 64738,
+ "constructor of created class with multiple select parameters"
+);
+
+$record = new it_dbi_test(array('foo' => 'bar'));
+is(
+ $record->ID,
+ 2,
+ "constructor of created class with single array parameter"
+);
+
+$record = new it_dbi($db + array('table' => "it_dbi_test"));
+is(
+ $record->x,
+ null,
+ "constructor without parameters"
+);
+
+$record = new it_dbi($db + array('table' => "it_dbi_test"), array('x >' => 0), "ORDER BY x DESC");
+is(
+ $record->x,
+ 64738,
+ "constructor with multiple select parameters"
+);
+
+$record->select(array('x' => 64738));
+is(
+ array($record->_key, $record->x, $record->foo),
+ array(3, 64738, "q'uux"),
+ "select"
+);
+
+$record->update(array('x' => 17));
+is(
+ array($record->_key, $record->x, $record->foo),
+ array(3, 17, "q'uux"),
+ "update"
+);
+
+is(
+ $record->update(array('x' => 18), array('x' => 17)),
+ 1,
+ "return affected rows",
+);
+
+is(
+ $record->update(array('x' => 18), array('x' => 17)),
+ 0,
+ "return zero affected rows",
+);
+
+$record->update(array('-x' => 'RAND() * 10'));
+isnt(
+ array($record->_key, $record->x, $record->foo),
+ array(3, 17, "q'uux"),
+ "update with function"
+);
+
+$rand = $record->x;
+is (
+ $record->_set(array('x' => $rand, 'foo' => "bar")),
+ "SET `foo`='bar'",
+ 'update: _set optimization'
+);
+
+$record->update(array('foo' => "bar"));
+$record->select(array('foo' => "bar"));
+$record->iterate();
+is(
+ array($record->_key, $record->x, $record->foo),
+ array(2, null, "bar"),
+ "iterate record 2"
+);
+$record->update(array('foo' => "qux"));
+$record->iterate();
+is(
+ array($record->_key, $record->x, $record->foo),
+ array(3, $rand, "bar"),
+ "iterate record 3"
+);
+$record->update(array('foo' => "quux"));
+
+$record->read(2);
+is(
+ array($record->_key, isset($record->x), $record->foo),
+ array(2, false, "qux"),
+ "iterate update record 2"
+);
+
+$record->read(3);
+is(
+ array($record->_key, $record->x, $record->foo),
+ array(3, $rand, "quux"),
+ "iterate update record 3"
+);
+
+is(
+ gettype($record->_key) . "/" . gettype($record->x) . "/" . gettype($record->_data['x']) . "/" . gettype($record->foo),
+ "integer/integer/integer/string",
+ "automatic type detection"
+);
+
+$count = 0;
+foreach (new it_dbi_test as $id => $record)
+{
+ $count++;
+ is($record->_key, $id, "Iterator id $id");
+}
+is($count, 3, "Iterator without select");
+
+$count = 0;
+foreach (new it_dbi_test(array('foo <>' => "")) as $id => $record)
+{
+ $count++;
+ is($record->_key, $id, "Iterator id $id");
+}
+is($count, 2, "Iterator with select");
+
+$count = 0;
+foreach ($record as $dummy_rec)
+ $count++;
+is($count, 2, "Iterator reused");
+
+# Test field localization feature
+
+$dbi->query('create temporary table it_dbi_testlocalized (
+ ID int not null auto_increment,
+ foobar_de varchar(42),
+ foobar_fr varchar(42),
+ primary key(ID)
+);');
+
+$record = new it_dbi($db + array('table' => "it_dbi_testlocalized"));
+$record->insert(array('foobar_de' => "deutsch", 'foobar_fr' => "franz"));
+$record->insert(array('foobar_de' => "deutsch2", 'foobar_fr' => "franz2"));
+
+T_set_language('de');
+$record->select(array());
+$record->iterate();
+is(
+ array($record->_key, $record->foobar),
+ array(1, "deutsch"),
+ "localized field foobar_de"
+);
+$record->iterate();
+is(
+ array($record->_key, $record->foobar),
+ array(2, "deutsch2"),
+ "localized field foobar_de iterate"
+);
+
+T_set_language('fr');
+$record->read(1);
+is(
+ array($record->_key, $record->foobar),
+ array(1, "franz"),
+ "localized field foobar_fr"
+);
+
diff --git a/devel-utf8/tests/it_html.t b/devel-utf8/tests/it_html.t
new file mode 100755
index 0000000..0def431
--- /dev/null
+++ b/devel-utf8/tests/it_html.t
@@ -0,0 +1,159 @@
+#!/www/server/bin/php -qC
+<?php
+
+# Tests for html.class
+
+# Traditional html generation
+new it_html(array('htmltype' => "html"));
+
+is(
+ a(array('href' => "&foo", 'true' => true, 'false' => false, 'null' => null, 'empty' => ""), "bar"),
+ '<a href="&amp;foo" true empty="">bar</a>',
+ "tag with attributes"
+);
+
+is(
+ div(),
+ "<div></div>\n",
+ "empty div tag"
+);
+
+is(
+ img(array('src' => "foo.png", 'alt' => "ALT")),
+ '<img src="foo.png" alt="ALT">',
+ "img tag with attributes"
+);
+
+is(
+ tag('link'),
+ "<link>\n",
+ "empty link tag"
+);
+
+is(
+ tag('link', "foo"),
+ "<link>foo</link>\n",
+ "link tag with data"
+);
+
+is(
+ it::replace(array('\n+\s*' => ""), select(array('name' => "gna", 'multiple' => true), '1:foo,2:bar', '1,2')),
+ '<select name="gna" multiple><option value="1" selected>foo</option><option value="2" selected>bar</option></select>',
+ "select tag with multiselect"
+);
+
+is(
+ it::replace(array('\n+\s*' => ""), select(array('name' => "gna"), array("1" => "foo", "2" => 'bar', '1,2' => "qux"), '1,2')),
+ '<select name="gna"><option value="1">foo</option><option value="2">bar</option><option value="1,2" selected>qux</option></select>',
+ "select tag without multiselect"
+);
+
+# XML generation
+unset($GLOBALS['it_html']);
+new it_html(array('htmltype' => "xhtml", 'tags' => "xmltest"));
+
+is(
+ xmltest(),
+ "<xmltest />\n",
+ "empty xmltest tag"
+);
+
+is(
+ xmltest("foo"),
+ "<xmltest>foo</xmltest>\n",
+ "empty xmltest tag"
+);
+
+is(
+ xmltest(array('href' => "&foo", 'true' => true, 'false' => false, 'null' => null, 'empty' => "")),
+ '<xmltest href="&amp;foo" true="true" empty="" />' . "\n",
+ "xmltest tag with attributes"
+);
+
+# Inheriting and extending it_html
+class myhtml extends it_html
+{
+function myimg($args)
+{
+ array_unshift($args, array('alt' => "ALT", 'bar' => "BAR"));
+
+ return parent::img($args);
+}
+}
+
+unset($GLOBALS['it_html']);
+new myhtml(array('htmltype' => "html"));
+
+is(
+ myimg(array('src' => "foo.gif", 'alt' => "foo")),
+ '<img alt="foo" bar="BAR" src="foo.gif">',
+ "it_html inheritance"
+);
+
+is(
+ it_html::sanitize(" \r \n " . ' <p><a href="http://www.flickr.com/people/swisspics%/">swisspics</a> posted < &lt; &auml; &amp; yesterday <b>a <i>photo</i></b> <b><i>tag missmatch</b></i>:</p><br><BR />
+
+<P><a href="javascript:window.close()" title="Wolken"><img src="http://farm1.static.flickr.com/177/377214376_bcba167a7d_m.jpg" width="240" height="180" alt="Wolken" style="border: 1px solid #ddd;" /></a></p>
+'),
+ ' <a href="http://www.flickr.com/people/swisspics%25/">swisspics</a> posted &lt; &lt; ä &amp; yesterday a <i>photo</i> <i>tag missmatch</i>:<br /><br /> <p><img src="http://farm1.static.flickr.com/177/377214376_bcba167a7d_m.jpg" alt="" /></p> ',
+ 'it_html::sanitize tag soup'
+);
+
+is(
+ it_html::sanitize('q&#8592;x'),
+ "q&#8592;x",
+ 'it_html::sanitize preserve numeric entities'
+);
+
+it_html::configure(array('charset' => "utf-8"));
+is(
+ it_html::sanitize('q&uuml;x'),
+ "q\xc3\xbcx",
+ 'it_html::sanitize with utf-8'
+);
+
+it_html::configure(array('charset' => "iso-8859-1"));
+is(
+ it_html::sanitize('q&uuml;x'),
+ "q\xfcx",
+ 'it_html::sanitize with latin1'
+);
+
+is(
+ it_html::sanitize('<b>a<br>b</b>'),
+ "<b>a<br />b</b>",
+ 'it_html::sanitize with b and br (tag prefix of other tag bug)'
+);
+
+is(
+ U("/foo.html", array('bar' => array('gna' => 42, 'qux' => array('quux' => "<Zürich>", 'gnöp' => "fasel")))),
+ '/foo.html?bar[gna]=42&bar[qux][quux]=%3CZ%FCrich%3E&bar[qux][gn%F6p]=fasel',
+ 'U() with nested arrays'
+);
+
+is(
+ U("Jet d'eau"),
+ 'Jet+d%27eau',
+ 'U() with single quotes in URL'
+);
+
+is(
+ U('%% %1%x %1x%x1%xx%11%ff%FF'),
+ '%25%25+%251%25x+%251x%25x1%25xx%11%ff%FF',
+ 'U() quoting of % if not followed by 2 hex digits'
+);
+
+is(
+ U('a\\b'),
+ 'a/b',
+ 'U() converting of \ to /'
+);
+
+is(it_html::entity_decode("&auml;"), "ä");
+is(it_html::entity_decode("&#8217;"), "'");
+is(it_html::entity_decode("&#x4a;"), "J");
+is(it_html::entity_decode("&#x4A;"), "J");
+is(it_html::entity_decode("&#xfff;"), " ");
+is(it_html::entity_decode("&#65;"), "A");
+is(it_html::entity_decode("&#999;"), " ");
+?>
diff --git a/devel-utf8/tests/it_text.t b/devel-utf8/tests/it_text.t
new file mode 100755
index 0000000..bc4d5c0
--- /dev/null
+++ b/devel-utf8/tests/it_text.t
@@ -0,0 +1,18 @@
+#!/www/server/bin/php
+<?php
+
+$obj->x = "attr";
+$obj->y->z = "attr";
+
+is(it_text::transmogrify(""), "");
+is(it_text::transmogrify("foo"), "foo");
+is(it_text::transmogrify("{foo}"), "");
+is(it_text::transmogrify("{foo}", array('foo' => 1)), "1");
+is(it_text::transmogrify("{foo}{foo}", array('foo' => 1)), "11");
+is(it_text::transmogrify("{foo}X", array('foo' => 1)), "1X");
+is(it_text::transmogrify("{foo}X{foo}", array('foo' => 1)), "1X1");
+is(it_text::transmogrify("X{foo}", array('foo' => 1)), "X1");
+is(it_text::transmogrify("X{foo}{bar}", array('foo' => 1, 'bar' => 2)), "X12");
+is(it_text::transmogrify("X{foo}", array('foo' => "&")), "X&");
+is(it_text::transmogrify("X{x}", $obj), "Xattr");
+is(it_text::transmogrify("X{y.z}", $obj), "Xattr");
diff --git a/devel-utf8/tests/it_url.t b/devel-utf8/tests/it_url.t
new file mode 100755
index 0000000..e8507aa
--- /dev/null
+++ b/devel-utf8/tests/it_url.t
@@ -0,0 +1,135 @@
+#!/www/server/bin/php -qC
+<?php
+
+# Tests for url.class, currently only constructor's parser
+
+# Create object and parse url
+$url = new it_url('HTTP://falcon:joshua@www.Relog.CH:80/default.asp');
+
+is(
+ $url->url,
+ 'http://www.relog.ch/',
+ '$url->url'
+);
+
+is(
+ $url->protocol,
+ 'http',
+ '$url->protocol'
+);
+
+is(
+ $url->hostname,
+ 'relog.ch',
+ '$url->hostname'
+);
+
+is(
+ $url->realhostname,
+ 'www.relog.ch',
+ '$url->realhostname'
+);
+
+is(
+ $url->port,
+ 80,
+ '$url->port'
+);
+
+is(
+ $url->path,
+ '',
+ '$url->path'
+);
+
+is(
+ $url->user,
+ 'falcon',
+ '$url->user'
+);
+
+is(
+ $url->pass,
+ 'joshua',
+ '$url->pass'
+);
+
+# and now check for path
+$url = new it_url('HTTP://falcon:joshua@www.Relog.CH:80/foo/bar.html');
+
+is(
+ $url->path,
+ 'foo/bar.html',
+ '$url->path'
+);
+
+$_SERVER['HTTP_HOST'] = "gna.ch";
+is(
+ it_url::absolute("/"),
+ 'http://gna.ch:/',
+ 'it_url::absolute basic'
+);
+
+$_SERVER['SERVER_PORT'] = 42;
+is(
+ it_url::absolute("/port"),
+ 'http://gna.ch:42/port',
+ 'it_url::absolute with non-standard port'
+);
+
+$_SERVER['HTTPS'] = true;
+$_SERVER['SERVER_PORT'] = 443;
+is(
+ it_url::absolute("/https"),
+ 'https://gna.ch/https',
+ 'it_url::absolute for https'
+);
+
+$url = new it_url('http://www.gna.ch/');
+$page = $url->get();
+is(
+ it::match('(</html>)', $page),
+ '</html>',
+ '$url->get with url in constructor'
+);
+
+$url = new it_url('http://bogus.url');
+$page = $url->get('http://www.gna.ch/');
+is(
+ it::match('(</html>)', $page),
+ '</html>',
+ '$url->get(url) with url as string arg'
+);
+
+$url = new it_url('http://bogus.url');
+$page = $url->get(array('url' => 'http://www.gna.ch/'));
+is(
+ it::match('(</html>)', $page),
+ '</html>',
+ '$url->get(\'url\' => url) with url as named arg'
+);
+is(
+ $url->result,
+ 200,
+ '$url->result = 200'
+);
+is(
+ $url->headers['Connection'],
+ 'close',
+ '$url->headers correctly set'
+);
+
+unset($url, $page);
+$page = it_url::get('http://www.gna.ch/');
+is(
+ it::match('(</html>)', $page),
+ '</html>',
+ 'it_url::get() static call'
+);
+
+$pages = it_url::get_multi('urls' => array('a' => 'http://www.gna.ch/', 'b' => 'http://search.ch/'));
+ok(it::match('</html>', $pages['a']), 'it_url::get_multi got first url');
+ok(it::match('</html>', $pages['b']), 'it_url::get_multi got second url');
+is(count($pages), 2, 'it_url::get_multi no additional array elements');
+
+?>
diff --git a/devel-utf8/tests/it_xml.t b/devel-utf8/tests/it_xml.t
new file mode 100755
index 0000000..f74c54b
--- /dev/null
+++ b/devel-utf8/tests/it_xml.t
@@ -0,0 +1,120 @@
+#!/www/server/bin/php -qC
+<?php
+
+# Tests for xml.class
+
+function match($xmldata, $expected, $name, $prefix = "", $p = array())
+{
+ $classname = $prefix ? ($prefix . "_xml") : "it_xml";
+ $varname = $prefix . "foo";
+ $xmldata = "<root>$xmldata</root>";
+ $xml = new $classname($xmldata, $p);
+
+ is(
+ preg_replace('/[#\s]+/', " ", print_r($xml->$varname, true)),
+ $expected,
+ "$name (string)"
+ );
+
+ $tmpfile = tmpfile();
+ fwrite($tmpfile, $xmldata);
+ rewind($tmpfile);
+
+ $xml = new $classname($tmpfile, $p);
+ fclose($tmpfile);
+
+ is(
+ preg_replace('/[#\s]+/', " ", print_r($xml->$varname, true)),
+ $expected,
+ "$name (file)"
+ );
+
+}
+
+match(
+ '<foo />',
+ 'foo Object ( ) ',
+ 'empty tag'
+);
+
+match(
+ '<foo /><foo />',
+ 'Array ( [0] => foo Object ( ) [1] => foo Object ( ) ) ',
+ 'multiple empty tags converted to array'
+);
+
+match(
+ '<foo title="Zürich">Stüssihofstadt</foo>',
+ 'foo Object ( [attr] => Array ( [title] => Zürich ) [val] => Stüssihofstadt ) ',
+ 'simple tag with latin1 content and attribute'
+);
+
+match(
+ '<foo><ns:a.b.-c ns2:d.e-f="value" /></foo>',
+ 'foo Object ( [a_b__c] => a_b__c Object ( [attr] => Array ( [d_e_f] => value ) ) ) ',
+ 'Tags and attributes with name space and special characters'
+);
+
+match(
+ '<foo>x &amp; y</foo>',
+ 'foo Object ( [val] => x & y ) ',
+ 'Character data with entities'
+);
+
+match(
+ '<foo>&amp;amp; &lt;a&gt; &#38;amp; &#60;b&#62; &#x26;amp; &#x3C;c&#x3E; &uuml;</foo>',
+ 'foo Object ( [val] => &amp; <a> &amp; <b> &amp; <c> ü ) ',
+ 'Predecode illegal entities while keeping properly encoded ones'
+);
+
+match(
+ '<foo>&amp;amp; &lt;a&gt; &#38;amp; &#60;b&#62; &#x26;amp; &#x3C;c&#x3E; &uuml;</foo>',
+ utf8_encode('foo Object ( [val] => &amp; <a> &amp; <b> &amp; <c> ü ) '),
+ 'Predecode illegal entities while keeping properly encoded ones (UTF-8)',
+ "",
+ array('encoding' => "UTF-8")
+);
+
+
+match(
+ "<foo>a\x05b</foo>",
+ 'foo Object ( [val] => a b ) ',
+ 'Illegal latin 1 character',
+ "",
+ array('encoding' => "ISO-8859-1")
+);
+
+# Test inheritance
+class my_xml extends it_xml
+{
+
+function my_xml($xmldata)
+{
+ parent::it_xml($xmldata);
+
+ # Code which should be executed in root and only there
+ $this->qux = new it_xml;
+ $this->qux->val = "qux";
+
+ if (is_object($this->myfoo))
+ $this->myfoo->inheritbaseclass = is_a($this->myfoo, "my_xml");
+}
+
+}
+
+match(
+ '<myfoo />',
+ 'myfoo Object ( [inheritbaseclass] => ) ',
+ 'Inheritance and constructor (critical for e.g. tel_xmlentry)',
+ 'my'
+);
+
+$x = new foo("<foo></foo>", array('prefix' => "test"));
+$x->set(array('gna' => 42, 'bar' => array('baz' => array("qux", "quux"))));
+match(
+ $x->to_xml(),
+ 'foo Object ( [gna] => gna Object ( [val] => 42 ) [bar] => bar Object ( [baz] => Array ( [0] => baz Object ( [val] => qux ) [1] => baz Object ( [val] => quux ) ) ) ) ',
+ "Method set()"
+);
+
+?>
diff --git a/devel-utf8/tests/itjs.t b/devel-utf8/tests/itjs.t
new file mode 100755
index 0000000..f616ced
--- /dev/null
+++ b/devel-utf8/tests/itjs.t
@@ -0,0 +1,50 @@
+#!/www/server/bin/php -qC
+<?php
+
+# Tests for itjs.class, currently only itjs::serialize()
+
+$_GET['aa'] = 1;
+
+is(
+ itjs::serialize(array()),
+ '[]',