feat: add bytes.indexOf, server.acceptBatch, server.pendingCount, stdin data callback, and coverage/valgrind make targets

Implement `bytesIndexOf` foreign function supporting optional start offset for searching byte sequences. Add `serverAcceptBatch` and `serverPendingCount` to net module for batch accepting connections and querying pending queue size. Refactor `stdinFileTimerCallback` to pass read bytes to Wren callback instead of null, with separate handling for EOF. Introduce `coverage_64bit` build config with gcov flags, plus `coverage`, `valgrind`, `clean-coverage`, and `publish` phony targets in Makefile. Fix memory leak in regex by nullifying freed pointers on allocation failure.
This commit is contained in:
2026-01-26 11:29:25 +00:00
parent 62b60cce36
commit 38de4da87d
24 changed files with 392 additions and 74 deletions
+22 -6
View File
@@ -27,6 +27,8 @@ parser.add_argument('--suffix', default='')
parser.add_argument('suite', nargs='?')
parser.add_argument('--skip-tests', action='store_true')
parser.add_argument('--skip-examples', action='store_true')
parser.add_argument('--valgrind', action='store_true',
help='Run tests under valgrind')
args = parser.parse_args(sys.argv[1:])
@@ -150,10 +152,15 @@ class Test:
return True
def run(self, app, type):
# Invoke wren and run the test.
def run(self, app, type, valgrind=False):
test_arg = self.path
proc = Popen([app, test_arg], stdin=PIPE, stdout=PIPE, stderr=PIPE)
if valgrind:
cmd = ['valgrind', '--leak-check=full', '--error-exitcode=99',
'--suppressions=' + join(dirname(realpath(__file__)), 'valgrind.supp'),
app, test_arg]
else:
cmd = [app, test_arg]
proc = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE)
# If a test takes longer than five seconds, kill it.
#
@@ -173,12 +180,14 @@ class Test:
if timed_out[0]:
self.fail("Timed out.")
else:
self.validate(type == "example", proc.returncode, out, err)
if valgrind and proc.returncode == 99:
self.fail("Valgrind detected memory errors")
self.validate(type == "example", proc.returncode, out, err, valgrind)
finally:
timer.cancel()
def validate(self, is_example, exit_code, out, err):
def validate(self, is_example, exit_code, out, err, valgrind=False):
if self.compile_errors and self.runtime_error_message:
self.fail("Test error: Cannot expect both compile and runtime errors.")
return
@@ -189,6 +198,13 @@ class Test:
except:
self.fail('Error decoding output.')
if valgrind:
err_lines = []
for line in err.split('\n'):
if not line.startswith('==') and not line.startswith('--'):
err_lines.append(line)
err = '\n'.join(err_lines)
error_lines = err.split('\n')
# Validate that an expected runtime error occurred.
@@ -376,7 +392,7 @@ def run_script(app, path, type):
# It's a skipped or non-test file.
return
test.run(app, type)
test.run(app, type, args.valgrind)
# Display the results.
if len(test.failures) == 0: