11 KiB
Test headless — citeste_curs_bnr (arhiva 10 zile + fisier anual BNR)
Tinta: COMUN\clase\onom_curs.vcx, clasa actualizare_curs_bnr, metoda citeste_curs_bnr
(patch v3, deja scris in binar — confirmat inainte de test, vezi sectiunea 0). Metoda a fost
apelata DIRECT, niciodata prin initializeaza — niciun apel la initializeaza() sau
scrie_curs_bnr() in tot scriptul, deci nicio scriere in Oracle. Conexiunea Oracle deschisa de
mediul de test (test_init_env_auto_roafacturare.prg) face doar SELECT-uri (firma, calendar,
pack_sesiune.set*) pentru initializarea sesiunii — nimic legat de cursuri BNR.
0. Confirmare inainte de test
COMUN\clase\onom_curs.vc2 are deja proprietatile clinkan/clinkarhiva si noua
citeste_curs_bnr cu parametrul tnSursa (linia 106+), identice cu blocul NOU din
docs\patch_curs_bnr_arhiva.md — verificat cu grep inainte de a scrie testul. .vcx/.VCT au
acelasi mtime cu .vc2 (22:11, 17.09.2026) — write-back-ul din docs\writeback_curs_bnr.md
confirmat aplicat, nu s-a atins din nou.
1. Artefact de harness gasit si ocolit (NU e defect de cod)
Apeland citeste_curs_bnr direct (fara initializeaza), primul apel a agatat testul (90s
timeout, 0 dialoguri detectate de watchdog_vfp.ps1). Cauza, confirmata prin proba minimala
(test_curs_bnr_probe2.prg, sters dupa confirmare):
citeste_curs_bnrincepe cucreeaza_backup_cursoare(This.cCursor)(onom_curs.vc2:118), care cheamacopiaza_structura_cursor()dinCOMUN\programe\oproceduri_comune.prg:3024.- Acolo,
If Used(tcSursa)(oproceduri_comune.prg:3027) — dacaccrsbnrnu e deja deschis (cazul cand chemi metoda direct, fara sa treci prininitializeaza, care il creeaza viagoExecutor.oExecute), cade peElsesi cheamaamessagebox("Eroare interna 2 - copiaza structura cursor",...)(oproceduri_comune.prg:3036). amessagebox(functia REALA,oproceduri_comune.prg:1205) e apelata din acelasi fisier cacopiaza_structura_cursor—mock_amessagebox.prgdocumenteaza explicit aceasta limita ("LIMITA 1: nu acopera sigur apelurile INTRA-FISIER") — deci mock-ul nu intercepteaza, se deschidemessagebox_formreal (MessageBox.vcx), modal, headless agata.- In productie nu se intampla:
initializeaza()creeazaThis.cCursorcugoExecutor.oExecute(lcSql, This.cCursor)(onom_curs.vc2:159) INAINTE de a chemaciteste_curs_bnr.
Reparatia e in test, nu in cod: inainte de FIECARE apel, testul precreaza ccrsbnr gol
(CREATE CURSOR ccrsbnr (Currency C(10), multiplier N(10,4), Curs N(14,6)) — campurile confirmate
din scrie_curs_bnr, onom_curs.vc2:282-283, care citeste exact Currency/multiplier/Curs
din cursor). Metoda oricum inchide cursorul (Use In) si il reconstruieste din raspunsul HTTP
(Xmltocursor), deci structura precreata conteaza doar pentru backup, nu pentru rezultat.
Confirmat cu proba minimala: dupa precreare, Return=0, Reccount=37, EUR curs=5.2637 — fara
agatare. Niciun fisier de productie nu a fost atins pentru asta.
2. Rezultate — 7 cazuri cerute + 1 caz suplimentar (cascada)
| # | Caz | Parametri | Return asteptat | Return obtinut | Durata | Rezultat |
|---|---|---|---|---|---|---|
| 1 | sursa 1, azi (zi lucratoare) | dData=17.09.2026 (joi) |
0 | 0 | 0.238s | PASS — Reccount=37, EUR curs=5.2637 |
| 2 | sursa 1, luni recenta | dData=14.09.2026 (luni) |
0 | 0 | 0.048s | PASS — cade pe publicarea de vineri, Reccount=37, EUR curs=5.2557 |
| 3 | sursa 2, martie an curent | dData=15.03.2026 |
0 | 0 | 0.084s | PASS — Reccount=37, EUR curs=5.0947 |
| 4 | sursa 2, 2 ianuarie an curent | dData=02.01.2026 |
0 | 0 | 0.202s | PASS — trecere in 2025, Reccount=38, EUR curs=5.0985 |
| 5 | sursa 1, data mult mai veche decat arhiva | dData=01.01.2026 |
2 | 2 | 0.047s | PASS — "data lipsa" distinct de "BNR picat" |
| 6 | sursa 1, host invalid (indisponibilitate) | cLinkArhiva=host .invalid inexistent, dData=azi |
1 | 2 | 0.181s | FAIL — vezi sectiunea 3, defect real in cod |
| 7 | fara parametru (compatibilitate inapoi) | dData=18.08.2026 |
0 (comportament sursa 0) | 0 | 0.041s | PASS — This.dData s-a suprascris la 18.09.2026 (publicare+1), ca inainte |
| 8 (suplimentar, cerut de coordonator) | cascada reala: acelasi obiect/dData din caz 5 (Return 2 pe sursa 1), apoi sursa 2 |
dData=01.01.2026 |
0 | 0 | 0.120s | PASS — Reccount=38, EUR curs=5.0985, FARA "Eroare interna 2" la al doilea apel |
Sumar: 7 PASS, 1 FAIL (cazul 6).
3. Cazul 5 — eroare tranzitorie auto-vindecata, nu afecteaza Return
La finalul cazului 5 (Return 2, data prea veche), logul a prins:
[ON ERROR] 13 Alias 'CCRSBNR' is not found. in REPUNE_BACKUP_CURSOARE linia 6363
Cauza: citeste_curs_bnr inchide This.cCursor (Use In) inainte de apelul HTTP; pe ramura
Return 2 cheama repune_backup_cursoare(This.cCursor) (onom_curs.vc2:175), a carei prima
linie utila e Select (tcOriginal) (oproceduri_comune.prg:6363) pe un alias deja inchis —
risc preexistent, deja documentat in docs\patch_curs_bnr_arhiva.md sectiunea 5, punctul 3
("repune_backup_cursoare pe cursor deja inchis"), nu introdus de acest patch. Confirmat acum ca
se reproduce efectiv. Efect: eroarea e prinsa de ON ERROR, executia continua la linia
urmatoare (lnRecno = Recno()), iar liniile de dupa (Select * From bckpccrsbnr Into Cursor ccrsbnr) reconstruiesc singure alias-ul ccrsbnr — auto-vindecare in aceeasi rulare, Return 2 final e corect si cazul 8 (cascada imediat urmatoare, sursa 2 pe acelasi obiect) confirma ca
ccrsbnr ramane intr-o stare corecta (Used, fara sa mai loveasca "Eroare interna 2" la
creeaza_backup_cursoare din apelul urmator). Nu s-a reparat codul — doar raportat, cum s-a cerut.
4. Cazul 6 — defect REAL, nu artefact de test
Return obtinut 2, asteptat 1. Nu e problema harnessului — e un gol real in
citeste_curs_bnr pentru cazul specific "host complet nerezolvabil" (nu doar HTTP non-200 sau
timeout pe conexiune).
Secventa exacta din log (prima eroare e cea reala, restul e cascada, exact ca in nota de procedura
despre ON ERROR):
[ON ERROR] 1429 OLE IDispatch exception ... WinHttp.WinHttpRequest: The server name or address
could not be resolved. in ACTUALIZARE_CURS_BNR.CITESTE_CURS_BNR (linia loHTTP.Send(), onom_curs.vc2:137)
[ON ERROR] 1429 ... The data necessary to complete this operation is not yet available. (citirea
ulterioara a lui loHTTP.Status, onom_curs.vc2:139)
... (cascada: 8x eroare 11 "Function argument value, type, or count is invalid" in bucla
Do While de la onom_curs.vc2:151-173, cu lcFisier ramas needefinit)
[ON ERROR] 13 Alias 'CCRSBNR' is not found. in REPUNE_BACKUP_CURSOARE linia 6363
Explicatie: loHTTP.Send() (onom_curs.vc2:137) NU e in TRY/CATCH si NU verifica intai daca
request-ul a esuat la nivel de retea/DNS — arunca direct o exceptie OLE cand hostul nu se rezolva.
Fara TRY/CATCH in metoda, ON ERROR global preia eroarea si, conform semanticii VFP (executia
continua la linia URMATOARE, nu la ramura Else corecta), programul "sare" peste blocul
If loHTTP.Status = 200 ... Else ... Return 1 ... Endif fara sa execute nici ramura de succes, nici
Return 1 — continua direct in bucla de cautare Cube cu lcFisier gol/nedefinit, epuizeaza cele
10 incercari (cascada de erori 11), si iese pe ramura "nimic gasit" -> Return 2. Rezultatul final
e gresit: un host complet indisponibil (DNS esuat) e raportat ca "data lipsa" (2), nu ca
"indisponibilitate" (1) — exact confuzia pe care patch-ul trebuia sa o elimine, dar doar pentru
raspunsuri HTTP non-200 de la un server care RASPUNDE, nu pentru esecul de rezolvare DNS.
Durata: 0.181s — nu agata deloc (departe de cele 5s/5s/5s/15s din SetTimeouts); esecul de
rezolvare DNS e instant, nu trece prin timeout-uri.
Conform instructiunii explicite: nu am reparat codul. Raportez cu dovada de mai sus.
5. Cum s-a rulat
Script: D:\ROA\ROAFACTURARE\COMUN\utile\Teste\test_curs_bnr_headless.prg (helper-e proprii:
crea_cursor_gol, log_txt, log_eroare, verifica_caz — toate in acelasi fisier).
Precompilare izolata:
powershell -ExecutionPolicy Bypass -File D:\ROA\ROAFACTURARE\COMUN\utile\Teste\_precompile.ps1 -Prg D:\ROA\ROAFACTURARE\COMUN\utile\Teste\test_curs_bnr_headless.prg
Rulare (proces separat, timeout 240s, in PowerShell):
$p = Start-Process -FilePath 'C:\Program Files (x86)\Microsoft Visual FoxPro 9\vfp9.exe' `
-ArgumentList '-A','-T','"D:\ROA\ROAFACTURARE\COMUN\utile\Teste\test_curs_bnr_headless.prg"' -PassThru
if (-not $p.WaitForExit(240000)) { $p.Kill() }
Log complet (marca unica de rulare in prima linie, SYS(2015)):
D:\ROA\ROAFACTURARE\COMUN\utile\Teste\_test_curs_bnr_out.txt — ultima rulare confirmata: mtime
17.09.2026 22:26, marca _7KA1C340N.
Retea: toate cele 8 sub-cazuri au ajuns efectiv la curs.bnr.ro (sau la hostul invalid pentru
cazul 6) — reteaua a functionat, niciun rezultat nu e raportat fals din lipsa de conectivitate.
6. Confirmare: nicio scriere in Oracle
Scriptul apeleaza EXCLUSIV loCurs.citeste_curs_bnr(...) pe obiecte actualizare_curs_bnr
instantiate direct — niciun apel la initializeaza() (care ar citi din Oracle si, la
Reccount=0, ar declansa cascada de UI) si niciun apel la scrie_curs_bnr() (singura metoda a
clasei care scrie in pack_curs.scrie_cotatii_curs). Singurele interactiuni cu Oracle din intreaga
rulare sunt cele din test_init_env_auto_roafacturare.prg (conectare + SELECT-uri de sesiune),
neschimbate fata de orice alt test headless din acest proiect.
7. Fisiere temporare de test, sterse dupa confirmare
test_curs_bnr_probe.prg / .fxp si test_curs_bnr_probe2.prg / .fxp (folosite doar pentru
diagnostic, sterse din COMUN\utile\Teste\ dupa ce artefactul de harness a fost confirmat si
reparat in scriptul final). Raman pe disc doar test_curs_bnr_headless.prg / .fxp si logul
_test_curs_bnr_out.txt.
8. Rerulare dupa reparatia Try/Catch (v4)
Data/ora: 17.09.2026 22:36. Reparatia din docs\patch_curs_bnr_arhiva.md sectiunea 7 (Try/Catch
in jurul ambelor loHTTP.Send() din citeste_curs_bnr) e scrisa in binar (write-back confirmat,
fidelity-check pe round-trip identic). .FXP vechi al testului sters, precompilat din nou, o
singura rulare vfp9 (-A -T), log nou confirmat pe mtime si marca (_7KA1CGZRZ, 22:36:54).
| # | Caz | Return inainte (sectiunea 2) | Return dupa | Rezultat |
|---|---|---|---|---|
| 1-4, 7, 8 | neschimbate | 0 | 0 | PASS (neschimbat) |
| 5 | data mult mai veche decat arhiva | 2 | 2 | PASS (neschimbat) |
| 6 | host invalid (indisponibilitate) | 2 (FAIL, asteptat 1) | 1 | PASS |
Sumar nou: 8 PASS, 0 FAIL (fata de 7 PASS, 1 FAIL inainte de reparatie). Nicio regresie pe
cazurile 1-5, 7, 8. Cazul 6 intoarce acum 1 ("BNR picat") in loc de 2 ("data lipsa"), deci
initializeaza ofera acum linkul https://www.cursbnr.ro/ in loc de mesajul gresit "Nu exista
cursul BNR pentru data specificata!".