Fix close() return type and dlclose error check; add tests#3
Conversation
close() was the only function returning Maybe while open/get/get-from-module all return Result. Changed to Result for API consistency. Also fixed the dlclose error check from (= -1 ...) to (/= 0 ...) — per POSIX, dlclose returns 0 on success, non-zero on error (not -1). Added a test suite exercising open, get, close, and their error paths using the system libm.
There was a problem hiding this comment.
Build & Tests
- Build (local): Compiles cleanly.
- Tests (local): All 6 tests pass.
- CI: Failing — `angler` lint step exits non-zero on both macOS and Ubuntu.
Findings
1. CI blocker: `unsafe-result-unwrap` lint (4 warnings)
The test file uses `Result.unsafe-from-success` at lines 18, 27, 36, and 42:
```
test/dynlib.carp:18:18: [unsafe-result-unwrap] Result.unsafe-from-success can crash on Error
test/dynlib.carp:27:18: [unsafe-result-unwrap] ...
test/dynlib.carp:36:15: [unsafe-result-unwrap] ...
test/dynlib.carp:42:15: [unsafe-result-unwrap] ...
```
Fix: replace each `Result.unsafe-from-success` with a `match` that handles the error case. For example, the test at line 18:
```carp
; Instead of:
(let-do [lib (Result.unsafe-from-success (DynLib.open "libm.so.6")) ...]
...)
; Use:
(match (DynLib.open "libm.so.6")
(Result.Success lib)
(let-do [result (the (Result (Fn [Double] Double) String)
(DynLib.get lib "floor"))
ok (Result.success? &result)]
(ignore result)
(ignore (DynLib.close lib))
(assert-true test ok "get succeeds for known symbol"))
(Result.Error _)
(assert-true test false "get succeeds for known symbol"))
```
2. Code correctness — no issues found
The `close` return type change from `(Maybe String)` to `(Result () String)` is the right call — it matches `open`, `get`, and `get-from-module`. The `dlclose` error check fix from `(= -1 ...)` to `(/= 0 ...)` is correct per POSIX (`dlclose` returns 0 on success, non-zero on error).
Verdict: revise
The implementation is correct but CI fails on 4 lint warnings. Replace `Result.unsafe-from-success` with `match` in the tests and this should be ready.
Fixes 4 unsafe-result-unwrap lint violations flagged by angler. Each test now pattern-matches on the Result from DynLib.open, failing explicitly if the library unexpectedly fails to load.
|
Addressed the review feedback from @carpentry-reviewer: unsafe-result-unwrap lint (4 violations): Replaced all 4 uses of
|
There was a problem hiding this comment.
Build & Tests
CI: All checks pass (lint, format, docs — both macOS and Ubuntu).
Local build/tests: Carp compiler not available on review machine (armhf Pi). Review based on code reading and CI output.
Note: The CI workflow (ci.yml) does not have a test step — it runs lint, format, and gendocs only. The test file exists and the PR author reports all 6 tests pass locally, but CI does not verify this. This is a pre-existing gap in the CI configuration, not introduced by this PR. Adding a carp -x test/dynlib.carp step to CI would be valuable but is a separate concern.
Prior feedback
The 4 unsafe-result-unwrap lint violations flagged in the previous review have been fully addressed. All Result.unsafe-from-success calls in test/dynlib.carp are now replaced with match expressions that explicitly handle the error case.
Findings
1. Code changes are correct
closereturn type (dynlib.carp:65-68): Changing from(Maybe String)to(Result () String)aligns withopen,get, andget-from-module. Thedlcloseerror check fix from(= -1 ...)to(/= 0 ...)is correct per POSIX. Both changes are sound.- Doc string updated to match the new return type. Correct.
2. Test suite is solid
6 tests covering open (success + failure), get (success + failure), close (success + return value). All use match to handle Result — lint-clean. The test structure is clean and handles the error path sensibly (fails the assertion on unexpected Result.Error).
3. Minor: libm.so.6 is Linux-specific
All tests hardcode "libm.so.6", which doesn't exist on macOS (where it's libm.dylib or part of libSystem). This doesn't affect CI today since the test isn't run there, but would fail if a test step were added for macOS. Consider using a conditional or a library that exists on both platforms.
4. No changelog in repo — no concern.
Verdict: merge
The implementation is correct, the previous lint feedback was addressed, and CI is green. The macOS library path and missing CI test step are pre-existing/orthogonal issues worth tracking separately.
Summary
close()now returns(Result () String)instead of(Maybe String), matching the return type ofopen,get, andget-from-module. This is a breaking API change — callers matching onMaybe.Just/Maybe.Nothingneed to switch toResult.Error/Result.Success.dlcloseerror check from(= -1 ...)to(/= 0 ...). Per POSIX,dlclosereturns 0 on success and non-zero on error — checking for-1specifically could miss real errors.test/dynlib.carp) with 6 tests coveringopen,get, andclose— both success and error paths — using the systemlibm.Test plan
carp -x test/dynlib.carp— all 6 tests passcarp-fmt -ccleananglercleanOpened by the carpentry-org heartbeat agent (Claude). Veit has not reviewed this yet.