#!/www/server/bin/php -qC true] ); _match( 'aBcD', ' aBcD ', 'aBcD', "caseinsensitive is default" ); _match( '\w+', 'Müller', 'Müller', '\w matches umlaut in utf-8 mode' ); _match( 'M.ller', 'Müller', 'Müller', '. matches umlaut in utf-8 mode' ); _match( utf8_decode('ö'), utf8_decode('Ö'), utf8_decode('Ö'), 'match umlaute in de_CH.latin1 case insensitive', ['utf8' => false] ); _match( utf8_decode('aöBÜ'), utf8_decode('AÖbü'), utf8_decode('AÖbü'), "match umlaute with non-utf-8 override in p", ['utf8' => false] ); _match( 'abc', "aBc", null, "set case sensitivity by parameter", ['casesensitive' => 1] ); _match( '\w+', 'word1 wörd2 word_3', ['word1', 'wörd2', 'word_3'], "test all => 1 without captures", ['all' => 1] ); _match( '\w+\s+(\d+)', 'word1 12 wörd2 3 word_3 4', ['12', '3', '4'], "test all => 1 with one capture", ['all' => 1] ); _match( '(\w+)\s+(\d+)', 'word1 12 wörd2 3 word_3 4', [['word1', '12'], ['wörd2', '3'], ['word_3', '4']], "test all => 1 with captures", ['all' => 1] ); _match( '(\w+)\s+(\d+)', 'word1 12 wörd2 3 word_3 4', [['word1', 'wörd2', 'word_3'], ['12', '3', '4']], "test all => 1,pattern_order => 1", ['all' => 1, 'pattern_order' => 1] ); ini_set('default_charset', 'iso-8859-1'); _match( 'aöBÜ', "AÖbü", 'AÖbü', "match utf-8 umlaute in case insensitive mode with utf8 override", ['utf8' => true] ); ini_set('default_charset', 'utf-8'); # # tests for it::replace() # is( it::replace( [ 'regex1' => 'repl1', 'regex2' => 'repl2', 'regex3' => 'repl3'], 'regex2 regex1 regex3'), 'repl2 repl1 repl3', 'test tr regex function' ); is(it::replace(['a' => "1", 'b' => "2"], "ab"), "12"); is(it::replace(['!' => "x"], "!"), "x"); is(it::replace(['\w' => "x"], "oö"), "xx"); is(it::replace(['[[:alpha:]]' => "x"], "ö"), "x"); is(it::replace(['\w' => "x", '#' => "!"], "#ö"), "!x"); is(it::replace(['#' => "!", '\w' => "x"], "#ö"), "!x"); is(it::replace(['ö' => "x"], "Ö"), "x"); is(it::replace(['a' => "1"], "aaa", ['limit' => 1]), "1aa"); is(it::replace(['\s' => "x"], it_html::entity_decode(" ")), "x", "match non-breaking space as white-space character"); is(it::replace(['a' => "b", 'b' => "c"], "a"), "c"); is(it::grep('ismatch', ['ismatch', 'isnomatch']), ['ismatch'], 'grep with simple regex'); is(it::grep('!', ['ismatch!', 'isnomatch']), ['ismatch!'], '! in regex'); is(it::grep('lower|UPPER', ['lower', 'LOWER', 'upper', 'UPPER'], ['casesensitive' => 1]), [0 => 'lower', 3 => 'UPPER'], 'set casesensitive'); is(it::grep('match', ['foo' => 'match', 'bar' => 'gna']), ['foo' => 'match'], 'with keys'); is(it::grep('2', [0 => 1, 1 => 2, 2 => 3], ['invert' => true]), [0 => 1, 2 => 3]); setlocale(LC_CTYPE, $oldlocale); ini_set('default_charset', $oldcharset); # end of tests that must run with specific charset # it::cidr_match tests is(it::cidr_match('192.168.2.3', '192.168.2.5'), false, "cidr_match full IP no match no mask"); is(it::cidr_match('192.168.2.3', '192.168.2.3'), true, "cidr_match full IP match no mask"); is(it::cidr_match('192.168.2.3', '192.168.2.5/32'), false, "cidr_match full IP no match"); is(it::cidr_match('192.168.2.5', '192.168.2.5/32'), true, "cidr_match full IP match"); is(it::cidr_match('192.168.1.1', '192.168.42.0/24'), false, "cidr_match no match"); is(it::cidr_match('192.168.42.1', '192.168.42.0/24'), true, "cidr_match basic match"); is(it::cidr_match('192.168.42.42', '192.168.0.0/16'), true, "cidr_match class b"); is(it::cidr_match('192.168.42.42', '192.168.42.64/26'), false, "cidr_match offset no match"); is(it::cidr_match('192.168.42.42', '192.168.42.32/27'), true, "cidr_match offset"); is(it::cidr_match('2001:918:ff83:101:798e:77c0:b722:fe56', '2001:918:ff83:101::/64'), true, "cidr_match ipv6"); is(it::cidr_match('2001:918:ff83:102:798e:77c0:b722:fe56', '2001:918:ff83:101::/64'), false, "cidr_match ipv6 no match" ); is(it::cidr_match('10.11.12.13', ['10.0.0.0/8', '192.168.0.0./16']), true, "cidr_match array"); # it::is_private_ip tests is(it::is_private_ip('192.168.2.3'), true, "is_private_ip 192.168/16 example"); is(it::is_private_ip('34.98.92.95'), false, "is_private_ip search.ch ipv4"); is(it::is_private_ip('2600:1901:0:6fe0::'), false, "is_private_ip search.ch ipv6"); is(it::is_private_ip('::1'), true, "is_private_ip loopback ipv6"); is(it::is_private_ip('172.19.34.19'), true, "is_private_ip 172.16/12 example"); is(it::is_private_ip('10.128.72.9'), true, "is_private_ip 10/8 example"); is(it::is_private_ip('195.49.47.11'), false, "is_private_ip gna.ch ipv4"); is(it::is_private_ip('2a01:2a8:9100:1911:abba:0:1:80'), false, "is_private_ip gna.ch ipv6"); is(it::is_private_ip('fd12::1337:bab3:d00d'), true, "is_private_ip fc00::/7 example"); is(it::is_private_ip('81.6.43.252'), false, "is_private_ip dunstkreis.ch ipv4"); is(it::is_private_ip('2a02:169:200:d::15'), false, "is_private_ip dunstkreis.ch ipv6"); is(it::is_private_ip('127.6.7.23'), true, "is_private_ip loopback ipv4"); is(it::is_private_ip('169.254.6.9'), true, "is_private_ip 169.254/16 example"); is(it::is_private_ip('gna.ch'), false, "is_private_ip gna.ch"); is(it::is_private_ip('dunstkreis.ch'), false, "is_private_ip dunstkreis.ch"); is(it::is_private_ip('loopback.gna.ch'), true, "is_private_ip loopback.gna.ch points to ::1"); is(it::is_private_ip('cname.gna.ch'), true, "is_private_ip cname.gna.ch points to loopback.gna.ch"); is(it::is_private_ip('pub4.gna.ch'), true, "is_private_ip pub4.gna.ch has public ipv4 but private ipv6"); is(it::is_private_ip('pub6.gna.ch'), true, "is_private_ip pub6.gna.ch has private ipv6 and public ipv6"); # Stuff which is interpreted by curl is(it::is_private_ip('127.1'), true, "is_private_ip loopback ipv4 (zeroes omitted)"); is(it::is_private_ip('127.0.0.01'), true, "is_private_ip loopback ipv4 (octal)"); is(it::is_private_ip('127.0.0.0x1'), true, "is_private_ip loopback ipv4 (hexadecimal)"); is(it::is_private_ip('127.01.0x1'), true, "is_private_ip private with omissions, octal and hexadecimal"); is(it::is_private_ip('128.01.0x1'), false, "TODO: is_private_ip non-private with omissions, octal and hexadecimal"); # it::filter_keys tests $data = ['a' => 1, 'b' => 2, 'c' => 3]; is(it::filter_keys($data, 'a'), ['a' => 1], "select one key"); is(it::filter_keys($data, ['a', 'b']), ['a' => 1, 'b' => 2], "select two keys with array"); is(it::filter_keys($data, 'a,b'), ['a' => 1, 'b' => 2], "select two keys with string"); is( array_keys(it::filter_keys($data, 'b,a')), ['a', 'b'], "keep order of data array per default"); is( array_keys(it::filter_keys($data, 'b,a', ['reorder' => true])), ['b', 'a'], "reorder with given key order"); # it::date tests function _time($debug_time, $expected) { $GLOBALS['debug_time'] = $debug_time; is(it::date(), $expected, ".time-$debug_time"); $GLOBALS['debug_time'] = ''; } _time("2014-01-01", "2014-01-01 00:00:00"); _time("2014-01-01-15-27-15", "2014-01-01 15:27:15"); _time("15-27", it::date('', '15:27')); _time("1527", it::date('', '15:27')); _time("15-27-15", it::date('', '15:27:15')); _time("152715", it::date('', '15:27:15')); _time("yesterday", it::date('', 'yesterday')); 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', it::time()), it::date('datetime'), 'recognize int as timestamp'); is(it::date('datetime', it::time()*1.0), it::date('datetime'), 'recognize float as timestamp'); is(it::date('datetime', it::time() . ''), it::date('datetime'), 'recognize digit string as timestamp'); is(it::date('datetime', '@' . it::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'); # it::uc* is(it::ucfirst('foo bär über'), 'Foo bär über'); is(it::ucwords('foo bär über'), 'Foo Bär Über'); # it::substr_replace is(it::substr_replace('abcdefgh', 'xyz', 2, 4), substr_replace('abcdefgh', 'xyz', 2, 4), 'it::substr_replace the same as substr_replace for ascii'); is(it::substr_replace('✔☯♥', '☃☃', 1, 1), '✔☃☃♥', 'it::substr_replace for utf-8'); is(it::substr_replace('', 'xyz', 0, 0), substr_replace('', 'xyz', 0, 0), 'it::substr_replace with empty haystack the same as substr_replace'); is(it::substr_replace('abc', 'xyz', 0, 2), substr_replace('abc', 'xyz', 0, 2), 'it::substr_replace replacing to end of haystack'); is(it::substr_replace('abc', 'xyz', 0, 10), substr_replace('abc', 'xyz', 0, 10), 'it::substr_replace replacing past end of haystack'); is(it::substr_replace('abcdefgh', 'xyz', 10, 4), substr_replace('abcdefgh', 'xyz', 10, 4), 'it::substr_replace outside of string'); is(grapheme_strlen("\xc1"), null, "need grapheme_strlen side effect for any2utf8"); is(it::any2utf8('Meier'), 'Meier', "it::any2utf8 ascii input"); is(it::any2utf8('Müller'), 'Müller', "it::any2utf8 utf8 input"); is(it::any2utf8('Aslı'), 'Aslı', "it::any2utf8 utf8 non-latin1 input"); is(it::any2utf8(utf8_decode('Müller')), 'Müller', "it::any2utf8 latin1 input"); is(it::any2utf8( ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'), # omit soft hyphen cause we filter it ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ', "it::any2utf8 utf8 input (exhaustive alphabet)"); is(it::any2utf8( utf8_decode(' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ')), ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ', "it::any2utf8 latin1 input (exhaustive alphabet)"); is(it::any2utf8(utf8_encode("ü")), "ü", "it::any2utf8 double encoding"); is(it::any2utf8("Meier"), "Meier", "it::any2utf8 ascii"); is(it::any2utf8("Müller"), "Müller", "it::any2utf8 utf-8 latin1"); is(it::any2utf8("Aslı"), "Aslı", "it::any2utf8 utf-8 non-latin1"); is(it::any2utf8("é»"), "é»", "it::any2utf8 utf-8 latin1 special combination"); is(it::any2utf8(utf8_encode("Müller")), "Müller", "it::any2utf8 doubly encoded utf8"); is(it::any2utf8(utf8_encode(utf8_encode("Müller"))), "Müller", "it::any2utf8 triply encoded utf8"); is(it::any2utf8(utf8_decode("Müller")), "Müller", "it::any2utf8 incorrectly encoded latin1"); is(it::any2utf8("a💚b"), "a💚b", "it::any2utf8 correctly handles 4-byte utf-8 character GREEN HEART"); is(it::any2utf8(["foo", utf8_decode("bär")]), ["foo", "bär"], "any2utf8 on arrays"); is(it::any2utf8(["foo", [utf8_decode("bär")]]), ["foo", ["bär"]], "any2utf8 on recursive arrays"); is(it::any2utf8([1, true, false, null]), [1, true, false, null], "any2utf8 should leave types alone"); is(it::any2utf8([utf8_decode('Müller') => utf8_decode('Müller')]), ['Müller' => 'Müller'], "it::any2utf8 latin1 keys"); is(it::any2utf8("\xc2\xad"), "", "it::any2utf8 remove soft hyphens"); foreach ([ 'a' => 'ä', 'e' => 'ë', 'i' => 'ï', 'o' => 'ö', 'u' => 'ü' ] as $src => $dst) { is(it::any2utf8("$src\xcc\x88"), $dst, "it::any2utf8 normalize combining diaeresis $dst to umlaut code $dst"); $src = mb_strtoupper($src); $dst = mb_strtoupper($dst); is(it::any2utf8("$src\xcc\x88"), $dst, "it::any2utf8 normalize combining diaeresis $dst to umlaut code $dst"); } is(it::any2utf8("\x65\xcc\x81"), "é", "it::any2utf8 convert to normal form C"); foreach ([$dummy, false, true, null, 1, "a", "Ä", "/", []] as $var) is(it::json_decode(it::json_encode($var)), $var); is(it::json_decode('{"foo":"bar"}')->foo, "bar"); is(it::json_decode('{"foo":"bar"}', ['assoc' => true])['foo'], "bar"); is(it::cdist(null), true); is(it::cdist(), true); errlike(function() {it::cdist(false);}, "invalid file name"); errlike(function() {it::cdist("foo", false, "bar");}, "invalid file name"); is(it::sort(["2!","19!","1!"]), ["1!", "19!", "2!"]); is(it::sort(["2!","19!","1!"], "r"), ["2!", "19!", "1!"]); is(it::sort(["2!","19!","1!"], "rn"), ["19!", "2!", "1!"]); is(it::sort(["ccc", "b", "aa"], "", function ($a, $b) { return strlen($a) <=> strlen($b); }), ["b", "aa", "ccc"]); is(it::sort(["ccc", "b", "aa"], function ($a, $b) { return strlen($a) <=> strlen($b); }), ["b", "aa", "ccc"]); is(it::sort(["ccc", "b", "aa"], "a", function ($a, $b) { return strlen($a) <=> strlen($b); }), [1 => "b", 2 => "aa", 0 => "ccc"]); is(it::sort(["ccc" => 2, "b" => 3, "aa" => 1], "k", function ($a, $b) { return strlen($a) <=> strlen($b); }), ['b' => 3, 'aa' => 1, 'ccc' => 2]); is(it::sort(["ccc", "b", "aa"], "strlen"), ["b", "aa", "ccc"]); is(it::mod(-9, 4), 3); is(it::mod(-8, 4), 0); is(it::mod(0, 4), 0); is(it::mod(7, 4), 3); is(it::map('5*$k+$v', [0 => 1, 1 => 2]), [1, 7]); is(it::map(function($k, $v) {return 5*$k+$v;}, [0 => 1, 1 => 2]), [1, 7]); is(it::map(function($v) {return 2*$v;}, [0 => 1, 1 => 2]), [2, 4]); is(it::map('strlen', ["aaa", "aa"]), [3, 2]); is(it::map('it::ucfirst', ["aaa"]), ["Aaa"]); $dom = new DOMDocument; $dom->loadXML('42'); is(it::map('$v->C14N()', $dom->childNodes), [ '42' ], "Traversable: Needs copy, not modifiable in-place"); # Special values which are not callable is(it::map('null', ["aaa", "aa"]), [null, null]); is(it::map('1', ["aaa", "aa"]), [1, 1]); is(it::map(42, ["aaa", "aa"]), [42, 42]); # Only map selected keys is(it::map('2*$v', [3, 4, 5], ['keys' => '0,1']), [6, 8, 5]); is(it::map('2*$v', [3, 4, 5], ['keys' => [0,1]]), [6, 8, 5]); is(it::map('2*$v', ['foo' => 1, 'bar' => 2], ['keys' => 'foo']), ['foo' => 2, 'bar' => 2]); # it::filter is(it::filter('$v > 2', [1, 5 => 2, 2 => 3]), [2 => 3]); is(it::filter('$k > 2', [1, 5 => 2, 2 => 3]), [5 => 2]); is(it::filter(function($v) {return $v > 2;}, [1, 5 => 2, 2 => 3]), [2 => 3]); is(it::filter(function($k, $v) {return $k > 2;}, [1, 5 => 2, 2 => 3]), [5 => 2]); is(it::split("b", "aba"), ["a", "a"]); is(it::split("b", "aBa"), ["a", "a"]); is(it::split("b", "abba"), ["a", "", "a"]); is(it::split("b", "ababa", ['limit' => 2]), ["a", "aba"]); is(it::split("b", "abbba", ['no_empty' => true]), ["a", "a"]); is(it::split("(b)", "aba", ['delim_capture' => true]), ["a", "b", "a"]); is(it::split("b", "aabaa", ['offset_capture' => true]), [["aa", 0], ["aa", 3]]); $tmpfile = tempnam("/tmp", "it_test"); it::file_put_contents($tmpfile, "abc"); is(($fh = it::fopen($tmpfile, "r")) ? fgets($fh) : null, "abc"); is(it::file_get_contents($tmpfile), "abc"); is(it::file_get_contents($tmpfile, false, null, 1), "bc"); is(it::file_get_contents($tmpfile, false, null, 0, 2), "ab"); is(it::file_get_contents($tmpfile, false, null, 1, 1), "b"); is(it::file($tmpfile), ["abc"]); ob_start(); it::readfile($tmpfile); is(ob_get_clean(), "abc"); it::file_put($tmpfile, "bb"); is(it::file_get($tmpfile), "bb"); unlink($tmpfile); requesturi(utf8_decode("lüönd"), "lüönd"); requesturi(utf8_decode("ü").utf8_encode("ü"), "üü"); requesturi(utf8_encode("müller"), "müller"); requesturi(utf8_encode(utf8_encode("müller")), "müller"); requesturi("I 💚 Nü York", "I 💚 Nü York"); function requesturi($teststring, $expect) { $_SERVER['REQUEST_URI'] = urlencode($teststring); it::params2utf8(); is(urldecode($_SERVER['REQUEST_URI']), $expect, "parms2utf8('$expect')"); # NOPHPLINT } _getopt(["val"], ['foo' => "val"]); _getopt(["--", "-val"], ['foo' => "-val"]); _getopt(["-v", "val"], ['verbose' => true, 'foo' => "val"]); _getopt(["--verbose", "val"], ['verbose' => true, 'foo' => "val"]); _getopt(["-vw", "val"], ['verbose' => true, 'werbose' => true, 'foo' => "val"]); _getopt(["-a", "val1", "val2"], ['arg' => "val1", 'foo' => "val2"]); _getopt(["--arg", "val1", "val2"], ['arg' => "val1", 'foo' => "val2"]); _getopt(["--arg=val1", "val2"], ['arg' => "val1", 'foo' => "val2"]); _getopt(["-va", "val1", "val2"], ['verbose' => true, 'arg' => "val1", 'foo' => "val2"]); _getopt(["-va", "-val1", "val2"], ['verbose' => true, 'arg' => "-val1", 'foo' => "val2"]); _getopt(["val1", "val2"], ['args' => ["val2"], 'foo' => 'val1']); function _getopt($in, $expect) { $_SERVER['argv'] = array_merge(["cmd.php"], $in); $opts = it::getopt(" Usage: test [OPTIONS] FOO [BAR] -v, --verbose Be verbose -w, --werbose Be werbose -a, --arg=ARG Have argument -b, --brg=ARG Have another arg "); is($opts, ['args' => $expect['args'] ?? []] + $expect); } is(it::urldecode("a%61%E4"), "aaä"); is(it::parse_str("%E4[%E4][%E4]=%E4"), ['ä' => ['ä' => ['ä' => 'ä']]]);