Bugfix Issue 1718 Legacy tcNotRunAnyPlatform Fatal - sebiboga/testlink-upgraded GitHub Wiki
Issue #1718 β Legacy tcNotRunAnyPlatform is fatally broken: requires the removed results.class.php and calls a method on null
Issue: #1718
Commits: 047111e9d (the fix) + 7287257e4 (regression suite + code-review corrections)
Branch: fix/issue-1718
Status: VERIFIED-FIXED (2026-09-29)
lib/results/tcNotRunAnyPlatform.php β the 1.9.20 "Test Report: Test Cases not run on
any Platform" controller β could not run at all. Every request to
/lib/results/tcNotRunAnyPlatform.php?tplan_id=<id> as any user holding
testplan_metrics answered HTTP 500 with a 0-byte body:
[26/Sep/29 13:38:01][WARNING][<nosession>][GUI]
E_WARNING
require_once(results.class.php): Failed to open stream: No such file or directory
- in .../lib/results/tcNotRunAnyPlatform.php - Line 16
[<<][6abbbf393d625757766614][DEFAULT][/lib/results/tcNotRunAnyPlatform.php][26/Sep/29 13:38:01][26/Sep/29 13:38:01][took 0.00275 secs]
Note the timing: one request, one warning, done in 2.75 ms. This is a hard fatal, not a hang and not a loop β anyone chasing a "slow report" theory would have been wrong.
It went unnoticed because the report was also missing from cfg/reports.cfg.php, so nothing
in the Reports ASIDE menu ever linked it. #1717 re-registered the report pointing at a modern
screen and filed this bug.
Environment. App http://localhost:8082 (PHP built-in server, docroot = repo root);
MariaDB 127.0.0.1:3306/testlink (testlink/testlink), freshly imported; user admin
(id 1, role 8) β holds testplan_metrics. Dataset rebuilt for the run by
php tmp/fixtures_1717.php: test project 1 (prefix TNR1717), test plan 2, platforms
1 = Windows 11 / 2 = Linux Ubuntu 22, build 1 (active+open) + build 2 (CLOSED), 5 test cases,
4 executions, plus a no-rights user tnrap1717norights (role 3).
Repro (the BFF login is CSRF-guarded, so a same-origin Origin header is required):
curl -s -c cj.txt -b cj.txt http://localhost:8082/login.php -o /dev/null
curl -s -c cj.txt -b cj.txt -X POST http://localhost:8082/api/auth/login \
-H "Origin: http://localhost:8082" -d "login=admin&password=admin"
curl -s -b cj.txt "http://localhost:8082/lib/results/tcNotRunAnyPlatform.php?tplan_id=2" \
-o /dev/null -w "HTTP %{http_code}\n" # β HTTP 500, 0 bytesMeasured, layer by layer.
| Layer | Measurement | Conclusion |
|---|---|---|
| server log |
logs/userlog1.log β one E_WARNING at Line 16, request completed in 2.75 ms |
request arrives, dies in the include |
| filesystem |
ls lib/functions/results.class.php β ENOENT |
the required file is gone |
| class |
grep -rn getMapOfLastResult over the tree β one pre-fix code call site (the controller's own :62), no definition anywhere |
the class is gone too β there is nothing to restore |
| isolated probe | the controller copied to a scratch file with only the require_once removed β HTTP 500, 0 bytes, and E_WARNING Undefined variable $re - in .../zz_probe_1718.php - Line 62
|
the second fatal is real, not a theory |
| same probe, no project selected |
HTTP 500 with <pre>#0 ...(38): testproject->get_by_id(0)</pre>
|
a third, unreported failure path |
| browser | the report is only reachable at gui/templates/results/tcNotRunAnyPlatform.html; 0 console errors
|
the modern path is clean, the legacy one is invisible in normal navigation |
The probe file was deleted immediately afterwards; it never entered the tree.
Four independent hard failures, all measured before a single line was changed:
-
:16βrequire_once('results.class.php'). The file does not exist, and the class it defined has no surviving implementation, so the include is a hard fatal. -
:49β// $re = new results(...)is commented out, while:62still runs$re->getMapOfLastResult()βUndefined variable $rethenCall to a member function getMapOfLastResult() on null. -
:59β// $executionsMap = $re->getSuiteList();is likewise commented out, while:124reads$executionsMap[$suiteId]and feeds it tosizeOf()at:133βsizeOf(null)TypeError. Latent: only reached once 1 and 2 are papered over. -
:37-40β$tplan_info['name']/$tproject_info['name']are read with no null guard.testproject::get_by_id(0)returnsnullrather than throwing (lib/functions/testproject.class.php:345-355throws only forNULL), so the failure surfaces at the missing name/prefix β:40/:42. This fires before the$refatal whenever no test project is selected.
Why it breaks now: it does not break β it never worked in 2.0.1. The 1.9.20 results class
and the getMapOfLastResult() query behind it were dropped when the report query layer was
replaced; the controller was left behind, unreachable from the menu, and it rotted unnoticed.
047111e9d deletes the three files:
| File | Lines |
|---|---|
lib/results/tcNotRunAnyPlatform.php |
273 |
gui/templates/dashio/results/tcNotRunAnyPlatform.tpl |
65 |
gui/templates/tl-classic/results/tcNotRunAnyPlatform.tpl |
66 |
(Line counts per git show 047111e9d --stat. Neither .tpl ends in a newline, so wc -l
undercounts each by one.)
This is the established repo pattern for a modernized screen: the four prior retirements are
332905e56 (cfieldsView), 596444f30 (issuetrackerView), a406f745d (codeTrackerView) and
029342980 (pluginView), all chore(<area>): delete legacy β¦ cluster.
No report is lost. Nothing in the application linked the dead file:
-
cfg/reports.cfg.php:270β the report'surlisgui/templates/results/tcNotRunAnyPlatform.html -
lib/general/asideMenu.php:238-240β the Reports ASIDE entry builds the same modern URL -
lib/functions/common.php:2094-2095β$actions->tcNotRunAnyPlatformis the same modern URL - no
{include file=β¦tcNotRunAnyPlatformβ¦}anywhere, and no cfieldsView-style hazard: template ownership is 1:1, becausetemplateConfiguration()derives the template frombasename($_SERVER['SCRIPT_NAME'])(lib/functions/common.php:938β:945$access_key . '.tpl'), the controller was the only script namedtcNotRunAnyPlatform, and nocfgremap exists -
directLinkis'', the print/export gateways only everinclude lib/results/printDocument.php, and thereports_listconsumers (api/resultsnav/index.php:173,api/aside/index.php:118,api/publiclink/index.php:160-161) all read the modern URL
No locale key was removed. link_report_not_run_on_any_platform is still live
(cfg/reports.cfg.php:269, lib/general/asideMenu.php:238) and tcversion_indicator is live in
8 other files.
Alternatives considered and rejected:
-
Re-add
lib/functions/results.class.phpβ there is no surviving implementation to restore, and the report's semantics are already re-implemented natively ontlTestPlanMetrics::getNeverRunByPlatform(). Writing it would be new code, not a fix. - Reduce the file to a redirect to the modern screen β it would have zero in-app callers (measured above) and is not the repo pattern.
- Comment out the broken statements β leaves ~200 lines of unreachable code that still advertises itself as a working report, which is the actual complaint.
7287257e4 additionally rewrites the three comments that the deletion made false
(lib/general/asideMenu.php, lib/functions/common.php, api/reports/index.php:4872 β they
said the dead controller "is not linked"). No logic changed in any of the three.
bash tmp/verify_1718.sh β 19 assertions, 19 PASS, 0 FAIL (exit 0).
The suite is deliberately not only "the file is gone" β a pure existence check would still pass if the deletion had taken the report with it:
| Group | Cases | What it pins |
|---|---|---|
| the fix | 1-6 | legacy URL answers 404; both .tpl + the .php deleted; no call site left in lib/; results.class.php still absent (the fix must not re-introduce the coupling) |
| the report survived | 7-12 | BFF status ok, 3 of 5 never-run, rows TNR1717-1 / TNR1717-4 / TNR1717-5 β identical to the pre-fix capture |
| the guards survived | 13-16 |
400 missing ids / 400 unknown plan / 400 foreign project / 403 measured through a real second login as tnrap1717norights
|
| the area survived | 17-19 | 0 new events rows beyond the 1-row pre-fix baseline; php -l on all 34 remaining lib/results/*.php; php tmp/test_1717.php still 40/40 PASS
|

Browser verification of the surviving report after the legacy cluster was retired
(http://localhost:8082/gui/templates/results/tcNotRunAnyPlatform.html?tproject_id=1&tplan_id=2):
renders "Found 3 of 5 test cases in this test plan", one column per platform
(Linux Ubuntu 22 / Windows 11), priority Medium, linkto.php?tprojectPrefix=TNR1717&item=testcase&id=β¦
deep links, design + Execution History popups, the "About this report" legend,
Elapsed seconds: 0.01 β 0 console errors/warnings. The Reports ASIDE entry still resolves
to the modern screen.
Event Viewer: the only log_level<16 rows from the whole session are id 3 (the original
require_once warning, i.e. the pre-fix evidence) and the deleted controller's own reproduction
probe. Every request after the fix added 0 rows.
Case 5 (no getMapOfLastResult() call site left in lib/) FAILED with 2 on its first run.
The two hits were not call sites but the #1717 explanatory comments in
lib/general/asideMenu.php:237 and lib/functions/common.php:2089. The real problem was
upstream: the "PASS β 0" reported for that case during the fix phase had been produced by a
grep run with a stale cd /tmp/opencode still in effect, so lib/ did not exist in the
current directory and grep matched nothing while reporting 0 β a silent false PASS.
The assertion now strips // and /* */ before counting, which is what the check was
supposed to mean.
2 BLOCKERs, 4 SHOULD-FIX, 4 NITs β all resolved:
-
BLOCKER β the CHANGELOG claimed "Regression suite 1718 8/8 PASS" while no suite existed
(the mandatory FIX-ISSUE.md Β§5 deliverable). Fixed:
tmp/verify_1718.sh+ theRegression β Issue #1718entry intmp/TLU_Test_Cases.md; the CHANGELOG now cites the real19/19 PASSand the harness command. -
BLOCKER β two deleted-file line counts were wrong (64/65 β the true 65/66, because
wc -lundercounts a file with no trailing newline). Fixed. - SHOULD-FIX β three of my own claims were imprecise and are now exact: the pre-fix run wrote
exactly one warning row (
eventsid 3), not "a row per request"; the:37-40failure surfaces at:40/:42becauseget_by_id(0)returnsnull; and there was one pre-fix code call site, not two. - The review confirmed the deletion is safe and complete, and that the scope is exactly right:
the single remaining
results.class.phpconsumer in the tree is the unregisteredlib/results/priorityBarChart.php:5.
-
#1719 β
lib/results/priorityBarChart.php:5requires the same removed../functions/results.class.phpand instantiates the same removedresultsclass at:17. Also unregistered; its line 2 even says//@TODO this file seems not to be in use. -
Four now-permanently-dead locale keys (their only users were the deleted cluster, each still
declared in 12
locale/*/strings.txt):title_test_report_not_run_on_any_platform,not_run_any_platform_status_msg,not_run_any_platform_no_platforms,info_tcNotRunAnyPlatform. Reported, not removed β rewriting 12 mixed-encoding catalogues is exactly the drive-by work a one-bug run must not do.
| File | Change |
|---|---|
lib/results/tcNotRunAnyPlatform.php |
deleted (273 lines) |
gui/templates/dashio/results/tcNotRunAnyPlatform.tpl |
deleted (65 lines) |
gui/templates/tl-classic/results/tcNotRunAnyPlatform.tpl |
deleted (66 lines) |
lib/general/asideMenu.php |
comment only |
lib/functions/common.php |
comment only |
api/reports/index.php |
comment only (not_run_any_platform block header) |
CHANGELOG |
2.0.1 [KEY BUGFIX] - #1718 entry |
tmp/verify_1718.sh |
new regression harness (19 assertions) |
tmp/TLU_Test_Cases.md |
Regression β Issue #1718 suite entry |
git checkout fix/issue-1718
php tmp/fixtures_1717.php # recreate the dataset (the DB is imported fresh every run)
bash tmp/verify_1718.sh # expect: 19 assertions, 19 PASS, 0 FAIL, exit 0
php tmp/test_1717.php # expect: 40 assertions, 40 PASS, 0 FAILBrowser: http://localhost:8082/index.php (admin/admin) β Metrics & Reports β Test Cases Not
Run on Any Platform. The legacy URL
http://localhost:8082/lib/results/tcNotRunAnyPlatform.php?tplan_id=2 must answer 404.