Files
comun/docs/depanare_testare_vfp.md

6.6 KiB

Depanare si testare VFP fara IDE (headless)

Metoda folosita la depanarea erorii "Property CNRCRT is not found" (ROACONT 2.11.61, 15.07.2026) - reutilizabila pentru orice bug runtime VFP. Complementara cu flux-editare-vfp-text.md (editare .vcx/.scx pe text) si cautare_vcx_vct.md (cautare).

0. Reguli de lucru

Vezi reguli_lucru.md (diff ca fisier + aprobare inainte de write-back, comentarii max o linie, modificari minime).

Fisiere de testare (foloseste-le la orice depanare/testare viitoare)

  • COMUN\utile\Teste\test_init_env_auto.prg - initializare completa de mediu FARA interactiune (parametri: host, schema, parola; implicit CENTRAL / MARIUSM_AUTO). Echivalentul headless al COMUN\programe\test_init_env.prg (care ramane varianta interactiva, cu INPUTBOX si meniu de lansare formulare).
  • COMUN\utile\Teste\test_repro_cnrcrt_footer.prg - exemplu complet de harness: init mediu -> replicare flux (cursoarele din modificanote) -> instantiere forma reala -> executie pas cu pas cu logare -> verdict OK/BUG. Copiaza-i structura pentru bug-uri noi.
  • COMUN\utile\Teste\teste_roacont.prg si COMUN\utile\Teste\test.prg - teste ad hoc istorice.
  • Mediu de test standard: server CENTRAL, schema MARIUSM_AUTO, parola schemei ROMFASTSOFT; utilizator de aplicatie "MARIUS M" / parola "123" (unde e nevoie de login).

1. Citirea log-ului aplicatiei (log.txt in radacina proiectului)

ErrorHandler (roacont.prg) scrie pentru fiecare eroare: nErrror, cMethod, line (0 daca exe-ul e compilat fara debug info) si stack-ul complet.

Semantica ON ERROR (esentiala la interpretare):

  • Dupa ce handlerul face RETURN, executia CONTINUA de la linia urmatoare din metoda care a crapat. O singura cauza produce deci CASCADE de erori.
  • Tipar clasic: eroare pe linia WITH <expr> => urmatoarele linii .prop = ... dau 1940 "Expression is not valid outside of WITH/ENDWITH", apoi ENDWITH da 1939 "WITH/ENDWITH mismatch". PRIMA eroare din secventa e cea reala; restul e zgomot.
  • Erorile din interiorul TRY/CATCH nu ajung in log (inghitite). Un CATCH gol poate ascunde ani de zile un defect latent, care "explodeaza" cand codul din jur se repara (exact cazul typo-ului oMinHeaderHeight din cusfonthandler).
  • In stack, liniile "ON..." sunt dispatch-uri (ON ERROR / READ EVENTS), nu metode reale.

2. Rulare headless a scripturilor VFP

Sablonul unui script de diagnostic (vezi utile\Teste\test_repro_cnrcrt_footer.prg):

  • logare in fisier cu STRTOFILE (nu WAIT WINDOW / debugger - nu exista consola);
  • ON ERROR DO <handler> WITH ERROR(), MESSAGE(), PROGRAM(), LINENO() care logheaza si continua - mimeaza comportamentul ErrorHandler din aplicatie;
  • QUIT obligatoriu la final (altfel ramane vfp9.exe agatat);
  • lansare din PowerShell cu timeout: $p = Start-Process 'C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe' -ArgumentList '-A','-T','"D:\...\script.prg" PARAM' -PassThru; $p.WaitForExit(120000); if (!$p.HasExited) { $p.Kill() }
  • -A ignora config, -T fara ecran de start; parametrul dupa .prg ajunge in LPARAMETERS.
  • LINENO() din handler e relativ la inceputul metodei (utile pentru localizare in .vc2: linia din metoda = linia raportata + linia PROCEDURE din .vc2).

Precautii: nu rula cu VFP IDE sau exe-ul aplicatiei deschis (lock pe binare); sterge .fxp-ul vechi de langa .prg daca ai editat scriptul intre rulari.

3. Mediu complet cu Oracle, fara interactiune

utile\Teste\test_init_env_auto.prg = varianta neinteractiva a programe\test_init_env.prg (fara INPUTBOX/xmenu): primeste host/schema/parola ca parametri, seteaza PATH/CLASSLIB/PROCEDURE ca roacont.prg, instantiaza goConn/goExecutor/goApp/goLog, incarca goFirma/goCalendar/optiuni si pachetele de sesiune Oracle. Dupa apel poti instantia forme reale (CREATEOBJECT('frm_xxx', ...)) si apela metodele lor punctual, cu cursoarele pregatite ca in fluxul real.

Pentru forme care se deschid modal (Show(1) blocheaza), nu apela Show: replica in script doar liniile relevante din Show (attach, calcule) si logheaza starea intre ele.

4. Bisectia versiunilor de clase (regresii)

Cand un bug apare "de azi", compara comportamentul cu clasa veche fara a atinge SVN:

  1. git show <rev_vechi>:clase/fisier.vcx > temp\fisier.vcx (+ .vct identic);
  2. convertit la text pentru diff: vcx2txt.ps1 -Source temp\fisier.vcx -CacheRoot temp\txt;
  3. in scriptul de test, SET CLASSLIB TO temp\fisier.vcx ADDITIVE (varianta veche) vs. cea din COMUN (varianta noua) - A/B pe acelasi flux;
  4. cand difera rezultatul, cauza e in diff-ul acelei clase (sau intr-un defect latent pe care noul cod il activeaza - vezi capcanele de mai jos).

5. Capcane VFP descoperite (de verificat la bug-uri asemanatoare)

  • SELECT ... INTO CURSOR NU mosteneste indecsii cursorului sursa. Orice Seek(..., 'cursor', 'tag') pe copie crapa. update_jtva_coloane creeaza INDEX ON id_jtva_coloana TAG id_jtva; daca ii copiezi rezultatul, recreeaza indexul.
  • Un grid isi pierde TOATE coloanele (ColumnCount devine 0, fara nicio eroare in log) daca un ControlSource crapa la re-evaluare in timp ce coloanele sunt atinse programatic (ex. FontName/FontSize per coloana in cusfonthandler.ApplyFontToGrid, la Init-ul formei prin _frmbase.SetFont). Simptome tipice in aval: _grdfooter.attachtogrid copiaza 0 coloane, apoi calctotal da "Property is not found" la Getpem(This, This.cColWithLabel).
  • ControlSource-uri cu campuri inexistente in RecordSource sunt tolerate la afisare, dar orice expresie care ARUNCA eroare la evaluare (Seek pe tag lipsa, functie nedefinita) declanseaza comportamentul de mai sus.
  • Fix-ul unui typo intr-o clasa partajata poate activa defecte latente in aval (codul care nu rulase niciodata incepe sa ruleze). La regresii dupa fix-uri "inofensive" in COMUN, cauta defectul latent, nu doar diff-ul.

6. Studiu de caz: "Property CNRCRT is not found" (15.07.2026)

Lant complet: frm_import_extrase_banca.modificanote copia crsJTVATemp fara index (defect latent) -> coloana cExplicatieTVA din frm_modific2024.grdRulaje face Seek(trul.id_jtva_coloana,'crsJtvaTemp','id_jtva') in ControlSource -> fix-ul typo-ului oMinHeaderHeight->nMinHeaderHeight in cusfonthandler (r17869) a facut ca ApplyFontToGrid sa atinga coloanele la Init -> grid-ul a ramas cu 0 coloane -> footer-ul a crapat in calctotal. Fix: INDEX ON id_jtva_coloana TAG id_jtva dupa SELECT INTO in modificanote. Repro/regresie: utile\Teste\test_repro_cnrcrt_footer.prg (mod FARAINDEX reproduce bug-ul, mod CUINDEX valideaza fix-ul).