Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions runtime/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,25 @@ Optional<string> f$iconv(const string &input_encoding, const string &output_enco
char *output_buf = output_str.buffer();

size_t res = iconv(cd, &input_buf, &input_len, &output_buf, &output_len);
if (res != (size_t)-1 || errno != E2BIG) {
// if errno is not E2BIG, then there is no need to allocate 4х more memory for a new string and try to call iconv function again
if (errno == E2BIG) {
/*
php_warning ("Error in iconv from \"%s\" to \"%s\" string \"%s\" at character %d at pos %d: %m", input_encoding.c_str(), output_encoding.c_str(), input_str.c_str(), (int)*input_buf, (int)(input_buf - input_str.c_str()));
*/
iconv(cd, nullptr, nullptr, nullptr, nullptr);
continue;
}
size_t len = output_buf - output_str.c_str();
/* when passing the value false to the string constructor(size_type size, bool b),
* the new string will have an internal size identical to the one passed,
* however in some cases iconv will not write anything to the output_buf
* and thus the string will actually be empty
*/
if (res != (size_t)-1 && (len != 0 || *output_str.c_str() == '\0')) {
output_str.shrink(static_cast<string::size_type>(output_buf - output_str.c_str()));
iconv_close(cd);
return output_str;
}
/*
if (errno != E2BIG) {
php_warning ("Error in iconv from \"%s\" to \"%s\" string \"%s\" at character %d at pos %d: %m", input_encoding.c_str(), output_encoding.c_str(), input_str.c_str(), (int)*input_buf, (int)(input_buf - input_str.c_str()));
break;
}
*/
iconv(cd, nullptr, nullptr, nullptr, nullptr);
}

iconv_close(cd);
Expand Down
13 changes: 9 additions & 4 deletions tests/kphp_tester.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ def __init__(self, file_path, test_tmp_dir, tags, env_vars: dict, out_regexps=No
def is_ok(self):
return "ok" in self.tags

def is_binary(self):
return "binary" in self.tags

def is_idempotent(self):
return "non-idempotent" not in self.tags

Expand Down Expand Up @@ -260,6 +263,7 @@ def run_warn_test(test: TestFile, runner):
runner.kphp_build_stderr_artifact.error_priority = -1
return TestResult.passed(test, runner.artifacts)


def run_runtime_not_warn_test(test: TestFile, runner):
if not runner.compile_with_kphp(test.env_vars):
return TestResult.failed(test, runner.artifacts, "got kphp build error")
Expand All @@ -275,6 +279,7 @@ def run_runtime_not_warn_test(test: TestFile, runner):

return TestResult.passed(test, runner.artifacts)


def run_runtime_warn_test(test: TestFile, runner):
if not runner.compile_with_kphp(test.env_vars):
return TestResult.failed(test, runner.artifacts, "got kphp build error")
Expand All @@ -300,7 +305,7 @@ def run_runtime_warn_test(test: TestFile, runner):
return TestResult.passed(test, runner.artifacts)


def run_ok_test(test: TestFile, runner):
def run_ok_test(test: TestFile, runner, binary):
# Run kphp test twice to check correctness in web-server alike environment with per request runtime reinitialization
runs_cnt = 2 if test.is_idempotent() else 1
if not runner.run_with_php(runs_cnt=runs_cnt):
Expand All @@ -309,7 +314,7 @@ def run_ok_test(test: TestFile, runner):
return TestResult.failed(test, runner.artifacts, "got kphp build error")
if not runner.run_with_kphp(runs_cnt=runs_cnt):
return TestResult.failed(test, runner.artifacts, "got kphp runtime error")
if not runner.compare_php_and_kphp_stdout():
if not runner.compare_php_and_kphp_stdout(binary=binary):
return TestResult.failed(test, runner.artifacts, "got php and kphp diff")

return TestResult.passed(test, runner.artifacts)
Expand All @@ -322,7 +327,7 @@ def run_test(use_nocc, cxx_name, test: TestFile):
runner = test.make_kphp_once_runner(use_nocc, cxx_name)
runner.remove_artifacts_dir()

if test.is_php8() and runner._php_bin is None: # if php8 doesn't exist on a machine
if test.is_php8() and runner._php_bin is None: # if php8 doesn't exist on a machine
test_result = TestResult.skipped(test)
elif test.is_kphp_should_fail():
test_result = run_fail_test(test, runner)
Expand All @@ -333,7 +338,7 @@ def run_test(use_nocc, cxx_name, test: TestFile):
elif test.is_kphp_runtime_should_not_warn():
test_result = run_runtime_not_warn_test(test, runner)
elif test.is_ok():
test_result = run_ok_test(test, runner)
test_result = run_ok_test(test, runner, binary=test.is_binary())
else:
test_result = TestResult.skipped(test)

Expand Down
20 changes: 20 additions & 0 deletions tests/phpt/string_functions/010_iconv.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
@ok binary
<?php

$original = "Привет мир";
$step1 = iconv('UTF-8', 'windows-1251', $original);
var_dump($step1);
$step2 = iconv('UTF-8', 'windows-1251', $step1);
var_dump($step2);

$empty = "";
var_dump(iconv('UTF-8', 'windows-1251', $empty));

// from examples: https://www.php.net/manual/en/function.iconv.php
$text = "This is the Euro symbol '€'.";
var_dump($text);
// TODO a strange bug when comparing via kphp_tester.py
//var_dump(iconv("UTF-8", "ISO-8859-1//TRANSLIT", $text));
// TODO works on MacOS but does not work on Linux
//var_dump(iconv("UTF-8", "ISO-8859-1//IGNORE", $text));
var_dump(iconv("UTF-8", "ISO-8859-1", $text));
4 changes: 2 additions & 2 deletions tests/python/lib/kphp_run_once.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def run_with_kphp(self, runs_cnt=1):

return kphp_server_proc.returncode == 0

def compare_php_and_kphp_stdout(self):
def compare_php_and_kphp_stdout(self, binary=False):
if self._kphp_server_stdout == self._php_stdout:
return True

Expand All @@ -143,7 +143,7 @@ def compare_php_and_kphp_stdout(self):
# just open and read the file - it's easier than messing with popen, etc.
with open(diff_artifact.file, 'r') as f:
print('diff: ' + f.read())
with open(diff_artifact.file, 'r') as f:
with open(diff_artifact.file, 'rb' if binary else 'r') as f:
print(f.read())

return False