diff --git a/docs/depanare_testare_vfp.md b/docs/depanare_testare_vfp.md index bfdc3fe..5356d13 100644 --- a/docs/depanare_testare_vfp.md +++ b/docs/depanare_testare_vfp.md @@ -1,225 +1,126 @@ -# 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\test_repro_import_nota.prg` - harness instantiere import_nota - (ROAGEST) fara Oracle: cursori dummy + goExecutor dummy; parametrul LPARAMETERS - incarca o copie de clasa din scratchpad in loc de cea reala (bisectie A/B). -- `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 ` => 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 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 :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). - -Varianta pe backup-uri de runda (fara git): copiaza `*.vc2.pre_rundaN.bak` din cache -intr-un folder temp ca `ointroduceri.vc2`, regenereaza binarul direct cu -`FoxBin2Prg.EXE "\fisier.vc2" "" "" "" 1 0 1` (pune `..\include\foxpro.h` langa, -altfel .ERR), apoi in harness incarca DOAR copia (nu ADDITIVE peste cea reala - -rezolvarea intre doua classlib-uri cu aceeasi clasa nu e garantata => fals negativ). -Bisectie in interiorul unei runde: neutralizeaza valori IN LOC (ControlSource -> -camp simplu, sterge linii de proprietate din mijlocul blocului) - NU sterge -obiecte/coloane din ADD OBJECT (strica structura: "Cannot add this object to a Grid"). - -## 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. -- **Literal string de peste 255 de caractere = eroare de COMPILARE, nu de runtime** (masurat - 24.07.2026: 255 trece, 256 pica). Mesajul difera dupa forma liniei: `Unrecognized command - verb` daca linia incepe cu un apel de metoda (`goExecutor.oExecuta("", 'c')`), - `Command contains unrecognized phrase/keyword` la o atribuire (`lc = ""`). - Insidios: restul programului ruleaza normal, doar linia aceea lipseste din `.fxp` si da - eroare 16 cand se ajunge la ea - deci un test poate raporta "FAIL" pe altceva decat cauza - reala. De aceea tot SQL-ul lung din codebase e scris cu `TEXT TO [TEXTMERGE] NOSHOW` - ... `ENDTEXT` sau concatenat din bucati, nu ca literal unic. Verificare rapida: - `awk 'length($0) > 260 {print NR": "length($0)}' fisier.prg`. -- **Coloana de grid cu ControlSource EXPRESIE (nu camp) cere `Bound = .F.`**. - Fara el: eroare 9 "Data type mismatch" la CREATEOBJECT-ul formei (faza de - constructie, raportata la linia apelanta, Details gol). Caz: import_nota.GridArt - Column7/8/9 cu `round(...)` (ROAGEST 16.07.2026); model corect: Grid1.cTaxCode - (`Bound = .F.` + expresie, functional de ani). - -## 6. Capcane la SCRIEREA scriptului de test (nu ale bug-ului investigat) - -Descoperite depanand harness-ul pentru "Data type mismatch" la `CREATEOBJECT('IMPORT_nota',...)` -(ROAGEST, 16.07.2026) - de verificat oricand un script de test nou pare "agatat". - -- **`DEFINE CLASS ... ENDDEFINE` NU poate sta la mijlocul programului principal.** - Daca il pui intre alte instructiuni de top-level (ex. clasa dummy pentru un - `goExecutor` de test, definita devreme "ca sa fie la indemana"), VFP compileaza - gresit: TOATE liniile de DUPA `ENDDEFINE` dau "Statement is not in a procedure" - (vezi `