#include "hbclass.ch" REQUEST HB_GT_STD_DEFAULT REQUEST HB_CODEPAGE_ESWIN PROCEDURE Main() LOCAL nFailures := 0 hb_cdpSelect( "ESWIN" ) InstallConsoleErrorHandler() nFailures += TestTLLEngine() IF nFailures == 0 LogLine( "TLLEngine Harbour OK" ) ELSE LogLine( "TLLEngine Harbour FAIL: " + hb_NToS( nFailures ) ) ENDIF ErrorLevel( nFailures ) RETURN FUNCTION TestTLLEngine() LOCAL cReport := "tools" + hb_ps() + "harbour" + hb_ps() + "tests" + hb_ps() + "fixtures" + hb_ps() + "api_report.lbl" LOCAL cLabel := "tools" + hb_ps() + "harbour" + hb_ps() + "tests" + hb_ps() + "fixtures" + hb_ps() + "api_label.lbl" LOCAL cHybridFile := "tools" + hb_ps() + "harbour" + hb_ps() + "tests" + hb_ps() + "fixtures" + hb_ps() + "hybrid_runtime.tmp" LOCAL cFaccli := "lbl" + hb_ps() + "faccli_00_importado_dominus.lbl" LOCAL cFaccliDatos := "lbl" + hb_ps() + "demo" + hb_ps() + "faccli_00_importado_dominus_sample_data.json" LOCAL cLl12Report := "lst-antiguos" + hb_ps() + "LST-Formatos-Estandar" + hb_ps() + "ESTANDAR" + hb_ps() + ; "faccli_00. Facturas a Clientes.lst" LOCAL cLl12Label := "lst-antiguos" + hb_ps() + ; "etiart_Etiquetas de Articulos por Codigo (LASER 4x14,21'2x52'5mm).lbl" LOCAL cLl12AskString := "lst-antiguos" + hb_ps() + "LSTpersonal" + hb_ps() + "MAINFO-DOMINUS" + hb_ps() + ; "albcli_#01. Albaranes a Clientes (MAINFO).lst" LOCAL cReportContent := MemoRead( cReport ) LOCAL cAskStringContent := StrTran( cReportContent, "DATOS.CLIENTE", '@cliente_preguntado' ) LOCAL cReportMissing := StrTran( cReportContent, "DATOS.CLIENTE", "DATOS.CLIENTE + DATOS.IMPORTE" ) LOCAL cReportTrimmed := TrimTrailingEol( cReportContent ) LOCAL cHybridCrLf := cReportContent + Chr( 13 ) + Chr( 10 ) + ; "[UserSection]" + Chr( 13 ) + Chr( 10 ) + ; "SQL=SELECT * FROM clientes WHERE importe>=10" + Chr( 13 ) + Chr( 10 ) + ; "MONEDA=" + Chr( 0x80 ) LOCAL cHybridLf := cReportContent + Chr( 10 ) + ; "[UserSection]" + Chr( 10 ) + "clave=valor" LOCAL cMarkerInJson := AddJsonEncodingProbe( cReportContent, "Ejemplo [UserSection]" ) LOCAL cInvalidHybrid := '{"cFormatVersion":' + Chr( 13 ) + Chr( 10 ) + ; "[UserSection]" + Chr( 13 ) + Chr( 10 ) + "SQL=INVALIDA" LOCAL cUtf8Probe := Utf8EncodingProbe() LOCAL cWinProbe := hb_UTF8ToStr( cUtf8Probe, "ESWIN" ) LOCAL cWinField := "3_desde_n" + Chr( 186 ) + "*factura*" LOCAL cUtf8Field := "3_desde_n" + Chr( 194 ) + Chr( 186 ) + "*factura*" LOCAL cReportProbeUtf8 := AddJsonEncodingProbe( cReportContent, cUtf8Probe ) LOCAL cDominusUtf8 := DominusEncodingProbe( cUtf8Probe, .T. ) LOCAL cDominusOldUtf8 := DominusEncodingProbe( cUtf8Probe, .F. ) LOCAL cLl12ListUtf8 := Ll12EncodingProbe( "[List description]", cUtf8Probe ) LOCAL cLl12LabelUtf8 := Ll12EncodingProbe( "[Label description]", cUtf8Probe ) LOCAL cPlantillaAntes LOCAL cContenidoAntes LOCAL cModoAntes LOCAL cContenidoInterno LOCAL cContenidoSalida LOCAL cFirmaHybrid LOCAL uResultado LOCAL oEngine LOCAL oDocumento LOCAL oDocumentoJson LOCAL oDocumentoHybrid LOCAL aPaginas LOCAL hJob LOCAL hAskStrings LOCAL hInputStats LOCAL nFailures := 0 cAskStringContent := StrTran( cAskStringContent, '"aObjects": [', '"hUserVars": {"CLIENTE_PREGUNTADO":{"formula":"AskString(\"Cliente\",False,\"Dominus\",20)"}},' + Chr( 13 ) + Chr( 10 ) + ' "aObjects": [' ) oEngine := TLLEngine():New():Create() oEngine:SetPlantillaContent( cAskStringContent ) hAskStrings := oEngine:GetAskStrings() nFailures += AssertEqual( "AskString se detecta antes de OpenJob", Len( hAskStrings ), 1 ) nFailures += AssertEqual( "AskString devuelve prompt", HashValue( HashValue( hAskStrings, "VAR.CLIENTE_PREGUNTADO", { => } ), "cPrompt", "" ), "Cliente" ) nFailures += AssertEqual( "AskString devuelve variable LL", HashValue( HashValue( hAskStrings, "VAR.CLIENTE_PREGUNTADO", { => } ), "cVariable", "" ), "VAR.CLIENTE_PREGUNTADO" ) nFailures += AssertEqual( "AskString devuelve valor por defecto", HashValue( HashValue( hAskStrings, "VAR.CLIENTE_PREGUNTADO", { => } ), "cDefault", "" ), "Dominus" ) nFailures += AssertEqual( "AskString devuelve preguntar por registro", HashValue( HashValue( hAskStrings, "VAR.CLIENTE_PREGUNTADO", { => } ), "lAskEveryRecord", .T. ), .F. ) nFailures += AssertEqual( "AskString devuelve longitud maxima", HashValue( HashValue( hAskStrings, "VAR.CLIENTE_PREGUNTADO", { => } ), "nMaxLength", 0 ), 20 ) oEngine:SetAskStringValue( "VAR.CLIENTE_PREGUNTADO", "Dulces Valero" ) oEngine:OpenJob() oDocumento := oEngine:RunEngine() aPaginas := oDocumento:GetPaginas() nFailures += AssertEqual( "AskString usa valor devuelto por Xailer", aPaginas[ 1 ][ "objetos" ][ 1 ][ "texto" ], "Dulces Valero" ) oEngine:End() oEngine := TLLEngine():New( cReport ):Create() nFailures += AssertEqual( "Encoding entrada predeterminado", oEngine:cInputEncoding, "WINDOWS-1252" ) nFailures += AssertEqual( "Encoding salida predeterminado", oEngine:cOutputEncoding, "WINDOWS-1252" ) cPlantillaAntes := oEngine:cPlantilla cContenidoAntes := oEngine:cPlantillaContent cModoAntes := oEngine:cPlantillaMode nFailures += AssertEqual( "Detecta LL-Dominus", oEngine:IsPlantillaLLDominus( cDominusUtf8 ), .T. ) nFailures += AssertEqual( "Detecta LL-Dominus antiguo", oEngine:IsPlantillaLLDominus( cDominusOldUtf8 ), .T. ) nFailures += AssertEqual( "Detecta listado LL12", oEngine:IsPlantillaLL12( hb_UTF8ToStr( cLl12ListUtf8, "ESWIN" ) ), .T. ) nFailures += AssertEqual( "Detecta etiqueta LL12", oEngine:IsPlantillaLL12( hb_UTF8ToStr( cLl12LabelUtf8, "ESWIN" ) ), .T. ) nFailures += AssertEqual( "Detecta listado LL12 real", oEngine:IsPlantillaLL12( MemoRead( cLl12Report ) ), .T. ) nFailures += AssertEqual( "Detecta etiqueta LL12 real", oEngine:IsPlantillaLL12( MemoRead( cLl12Label ) ), .T. ) nFailures += AssertEqual( "Detecta LL12 real con AskString", oEngine:IsPlantillaLL12( MemoRead( cLl12AskString ) ), .T. ) nFailures += AssertEqual( "JSON ajeno no es LL-Dominus", oEngine:GetTipoPlantilla( '{"valor":1}' ), "DESCONOCIDO" ) nFailures += AssertEqual( "Texto invalido desconocido", oEngine:GetTipoPlantilla( "texto sin formato" ), "DESCONOCIDO" ) nFailures += AssertEqual( "Tipo LL-Dominus", oEngine:GetTipoPlantilla( cDominusUtf8 ), "LLDOMINUS" ) nFailures += AssertEqual( "Tipo LL12", oEngine:GetTipoPlantilla( hb_UTF8ToStr( cLl12ListUtf8, "ESWIN" ) ), "LL12" ) nFailures += AssertEqual( "Deteccion conserva nombre", oEngine:cPlantilla, cPlantillaAntes ) nFailures += AssertEqual( "Deteccion conserva contenido", oEngine:cPlantillaContent, cContenidoAntes ) nFailures += AssertEqual( "Deteccion conserva modo", oEngine:cPlantillaMode, cModoAntes ) oEngine:SetEncodingUTF8() nFailures += AssertEqual( "Detecta LL-Dominus UTF8", oEngine:IsPlantillaLLDominus( cDominusUtf8 ), .T. ) nFailures += AssertEqual( "Detecta LL12 UTF8", oEngine:IsPlantillaLL12( cLl12LabelUtf8 ), .T. ) oEngine:Init( cReport ) nFailures += AssertEqual( "Init restablece encoding entrada", oEngine:cInputEncoding, "WINDOWS-1252" ) nFailures += AssertEqual( "Init restablece encoding salida", oEngine:cOutputEncoding, "WINDOWS-1252" ) oEngine:OpenJob() nFailures += AssertEqual( "IsUsedVar compatible", oEngine:IsUsedVar( "DATOS.CLIENTE" ), .T. ) nFailures += AssertEqual( "Variable faltante detectada", Len( oEngine:GetVariablesFaltantes() ), 1 ) nFailures += AssertEqual( "Nombre variable faltante", oEngine:GetVariablesFaltantes()[ 1 ], "DATOS.CLIENTE" ) oEngine:SendDataVar( "DATOS", { "CLIENTE" => "Cliente API" } ) oEngine:SendDataVarAt( 1, "DATOS", { "CLIENTE" => "Cliente ruptura A" } ) oEngine:SendDataVarAt( 2, "DATOS", { "CLIENTE" => "Cliente ruptura B" } ) nFailures += AssertEqual( "Datos completos", Len( oEngine:GetVariablesFaltantes() ), 0 ) hJob := oEngine:CloseJob() nFailures += AssertEqual( "CloseJob struct var", Len( hJob[ "aStructVar" ] ), 1 ) nFailures += AssertEqual( "CloseJob conserva cambios DataVar", Len( hJob[ "aDataVarChanges" ] ), 2 ) nFailures += AssertEqual( "Indice segundo cambio DataVar", hJob[ "aDataVarChanges" ][ 2 ][ "nIndiceDetalle" ], 2 ) oDocumento := oEngine:RunEngine() aPaginas := oDocumento:GetPaginas() nFailures += AssertEqual( "Engine report texto", aPaginas[ 1 ][ "objetos" ][ 1 ][ "texto" ], "Cliente API" ) nFailures += AssertEqual( "Engine report ancho", oDocumento:nAncho, 80 ) oEngine:End() hb_cdpSelect( "EN" ) oEngine := TLLEngine():New( cReport ):Create() oEngine:OpenJob() oEngine:SendDataVar( "PRUEBA", { cWinField => "valor" } ) hJob := oEngine:CloseJob() nFailures += AssertEqual( ; "Nombre CP1252 independiente de pagina activa", ; hJob[ "aStructVar" ][ 1 ][ "nombre" ], ; cUtf8Field ) oEngine:End() hb_cdpSelect( "ESWIN" ) oEngine := TLLEngine():New( cReport ):Create() oEngine:SetEncodingUTF8() oEngine:OpenJob() oEngine:SendDataVar( "PRUEBA", { cUtf8Field => "valor" } ) hJob := oEngine:CloseJob() nFailures += AssertEqual( ; "Nombre UTF8 no se convierte dos veces", ; hJob[ "aStructVar" ][ 1 ][ "nombre" ], ; cUtf8Field ) oEngine:End() oEngine := TLLEngine():New():Create() oEngine:SetEncodingUTF8() oEngine:SetPlantillaContent( cReportContent ) oEngine:OpenJob() nFailures += AssertEqual( "Plantilla mediante contenido", oEngine:IsUsedVar( "DATOS.CLIENTE" ), .T. ) oEngine:End() oEngine := TLLEngine():New():Create() oEngine:SetPlantillaContent( cReportContent + Chr( 13 ) + Chr( 10 ) ) nFailures += AssertEqual( "JSON puro conserva CRLF final", oEngine:cPlantillaContent, cReportContent + Chr( 13 ) + Chr( 10 ) ) oEngine:End() oEngine := TLLEngine():New():Create() nFailures += AssertEqual( "Guarda fixture hibrida", HB_MemoWrit( cHybridFile, cHybridCrLf, .F. ), .T. ) oEngine:SetPlantillaContent( MemoRead( cHybridFile ) ) nFailures += AssertEqual( "Hibrida CRLF extrae solo JSON", oEngine:cPlantillaContent, cReportTrimmed ) oEngine:OpenJob() oEngine:SendDataVar( "DATOS", { "CLIENTE" => "Cliente hibrido" } ) oDocumentoHybrid := oEngine:RunEngine() nFailures += AssertEqual( "Hibrida CRLF genera IR", HB_ISOBJECT( oDocumentoHybrid ), .T. ) cFirmaHybrid := DocumentoFirma( oDocumentoHybrid ) oEngine:End() FErase( cHybridFile ) oEngine := TLLEngine():New():Create() oEngine:SetPlantillaContent( cHybridLf ) nFailures += AssertEqual( "Hibrida LF extrae solo JSON", oEngine:cPlantillaContent, cReportTrimmed ) oEngine:End() oEngine := TLLEngine():New():Create() oEngine:SetPlantillaContent( cMarkerInJson ) nFailures += AssertEqual( "Marcador dentro de JSON no corta", oEngine:cPlantillaContent, cMarkerInJson ) oEngine:End() oEngine := TLLEngine():New():Create() oEngine:SetPlantillaContent( cInvalidHybrid ) nFailures += AssertEqual( "JSON invalido se conserva antes de seccion", oEngine:cPlantillaContent, '{"cFormatVersion":' ) oEngine:OpenJob() nFailures += AssertEqual( "JSON invalido no incorpora UserSection", Len( oEngine:oPlantillaRuntime:GetData() ), 0 ) oEngine:End() oEngine := TLLEngine():New():Create() oEngine:SetPlantillaContent( cReportContent ) oEngine:OpenJob() oEngine:SendDataVar( "DATOS", { "CLIENTE" => "Cliente hibrido" } ) oDocumentoJson := oEngine:RunEngine() nFailures += AssertEqual( ; "IR hibrido identico a JSON puro", ; cFirmaHybrid, ; DocumentoFirma( oDocumentoJson ) ) oEngine:End() oEngine := TLLEngine():New():Create() oEngine:SetPlantillaContent( cReportMissing ) oEngine:OpenJob() oDocumento := oEngine:RunEngine() nFailures += AssertEqual( "RunEngine devuelve NIL con datos ausentes", oDocumento == NIL, .T. ) nFailures += AssertEqual( "cLastError incluye DATOS.CLIENTE", At( "DATOS.CLIENTE", oEngine:cLastError ) > 0, .T. ) nFailures += AssertEqual( "cLastError incluye DATOS.IMPORTE", At( "DATOS.IMPORTE", oEngine:cLastError ) > 0, .T. ) oEngine:End() oEngine := TLLEngine():New( "plantilla_anterior_inexistente.lbl" ):Create() oEngine:SetEncodingUTF8() oEngine:SetPlantillaContent( cReportContent ) oEngine:OpenJob() nFailures += AssertEqual( "Contenido sobrescribe nombre", oEngine:IsUsedVar( "DATOS.CLIENTE" ), .T. ) oEngine:End() oEngine := TLLEngine():New():Create() oEngine:SetEncodingWIN() nFailures += AssertEqual( "SetEncodingWIN entrada", oEngine:cInputEncoding, "WINDOWS-1252" ) nFailures += AssertEqual( "SetEncodingWIN salida", oEngine:cOutputEncoding, "WINDOWS-1252" ) oEngine:SetPlantillaContent( cReportProbeUtf8 ) cContenidoInterno := oEngine:cPlantillaContent nFailures += AssertEqual( "SetEncodingWIN no convierte plantilla", cContenidoInterno, cReportProbeUtf8 ) oEngine:OpenJob() nFailures += AssertEqual( "Plantilla UTF8 con encoding WIN", oEngine:oPlantillaRuntime:GetData()[ "cEncodingProbe" ], cUtf8Probe ) oEngine:SendDataVar( "DATOS", { "CLIENTE" => cWinProbe } ) oDocumento := oEngine:RunEngine() aPaginas := oDocumento:GetPaginas() nFailures += AssertEqual( "RunEngine plantilla UTF8 con datos WIN", aPaginas[ 1 ][ "objetos" ][ 1 ][ "texto" ], cUtf8Probe ) oEngine:OpenJob() nFailures += AssertEqual( "Plantilla no convierte dos veces", oEngine:cPlantillaContent, cContenidoInterno ) cContenidoSalida := oEngine:GetPlantillaContent() nFailures += AssertEqual( "Salida plantilla siempre UTF8", cContenidoSalida, cReportProbeUtf8 ) oEngine:SetOutputEncoding( "UTF8" ) cContenidoSalida := oEngine:GetPlantillaContent() nFailures += AssertEqual( "Salida plantilla independiente del encoding", cContenidoSalida, cReportProbeUtf8 ) oEngine:End() oEngine := TLLEngine():New():Create() oEngine:SetEncodingUTF8() nFailures += AssertEqual( "SetEncodingUTF8 entrada", oEngine:cInputEncoding, "UTF-8" ) nFailures += AssertEqual( "SetEncodingUTF8 salida", oEngine:cOutputEncoding, "UTF-8" ) oEngine:SetPlantillaContent( cReportProbeUtf8 ) oEngine:OpenJob() nFailures += AssertEqual( "Plantilla UTF8 conservada", oEngine:oPlantillaRuntime:GetData()[ "cEncodingProbe" ], cUtf8Probe ) nFailures += AssertEqual( "Getter conserva UTF8", At( cUtf8Probe, oEngine:GetPlantillaContent() ) > 0, .T. ) oEngine:SendDataVar( "DATOS", { "CLIENTE" => cUtf8Probe } ) oDocumento := oEngine:RunEngine() aPaginas := oDocumento:GetPaginas() nFailures += AssertEqual( "SendDataVar UTF8 conservado", aPaginas[ 1 ][ "objetos" ][ 1 ][ "texto" ], cUtf8Probe ) uResultado := oEngine:SetEncoding( "CP1252", "UTF-8" ) nFailures += AssertEqual( "SetEncoding valido devuelve Self", HB_ISOBJECT( uResultado ), .T. ) nFailures += AssertEqual( "SetEncoding alias entrada", oEngine:cInputEncoding, "WINDOWS-1252" ) nFailures += AssertEqual( "SetEncoding alias salida", oEngine:cOutputEncoding, "UTF-8" ) uResultado := oEngine:SetInputEncoding( "invalida" ) nFailures += AssertEqual( "Encoding invalido devuelve falso", HB_ISLOGICAL( uResultado ) .AND. ! uResultado, .T. ) nFailures += AssertEqual( "Encoding invalido conserva entrada", oEngine:cInputEncoding, "WINDOWS-1252" ) nFailures += AssertEqual( "Encoding invalido informa error", Len( oEngine:cEncodingError ) > 0, .T. ) oEngine:End() oEngine := TLLEngine():New():Create() oEngine:SetEncodingWIN() oEngine:SetPlantillaContent( cReportContent ) oEngine:OpenJob() oEngine:SendDataVar( "DATOS", { "CLIENTE" => cWinProbe } ) oDocumento := oEngine:RunEngine() aPaginas := oDocumento:GetPaginas() nFailures += AssertEqual( "SendDataVar CP1252 normalizado", aPaginas[ 1 ][ "objetos" ][ 1 ][ "texto" ], cUtf8Probe ) oEngine:End() oEngine := TLLEngine():New():Create() oEngine:SetPlantillaContent( "{}" ) oEngine:SetPlantillaName( cReport ) oEngine:OpenJob() nFailures += AssertEqual( "Nombre sobrescribe contenido", oEngine:IsUsedVar( "DATOS.CLIENTE" ), .T. ) oEngine:End() oEngine := TLLEngine():New():Create() oEngine:SetPlantillaContent( MemoRead( cFaccli ) ) oEngine:OpenJob() nFailures += AssertEqual( "Variable conserva nombre original", AScan( oEngine:GetVariablesUsadas(), "OMEMQUERY.iva1" ) > 0, .T. ) nFailures += AssertEqual( "Operador AND no es variable", AScan( oEngine:GetVariablesUsadas(), "AND.Len" ), 0 ) oEngine:End() oEngine := TLLEngine():New( cLabel ):Create() oEngine:OpenJob() hJob := oEngine:GetLabelPrintLayout() nFailures += AssertEqual( "Layout impresion detecta etiquetas", hJob[ "lLabelDocument" ], .T. ) nFailures += AssertEqual( "Layout impresion ancho papel", hJob[ "nPaperWidth" ], 100.0 ) nFailures += AssertEqual( "Layout impresion alto papel", hJob[ "nPaperHeight" ], 50.0 ) nFailures += AssertEqual( "Layout impresion capacidad", hJob[ "nCapacity" ], 4 ) oEngine:SendDetalleSchema( "LINEAS", { "NOMBRE" => "" } ) nFailures += AssertEqual( "Detalle vacio conserva esquema", oEngine:ValidarDatos()[ "lOk" ], .T. ) hJob := oEngine:CloseJob() nFailures += AssertEqual( "Detalle vacio no crea registros", Len( hJob[ "aRegLine" ] ), 0 ) nFailures += AssertEqual( "Detalle vacio declara campos", Len( hJob[ "aStructLine" ] ), 1 ) oEngine:End() oEngine := TLLEngine():New( cLabel ):Create() oEngine:OpenJob() oEngine:SetInputDiagnostics( .T. ) oEngine:SetEtiquetaInicial( 3 ) oEngine:SendDetalle( "LINEAS", { "NOMBRE" => cWinProbe } ) oEngine:SendDetalle( "LINEAS", { "NOMBRE" => "Dos" } ) oEngine:SendDetalle( "LINEAS", { "NOMBRE" => "Tres" } ) oEngine:SendDetalle( "LINEAS", { "NOMBRE" => "Cuatro" } ) oEngine:SendDetalle( "LINEAS", { "NOMBRE" => "Cinco" } ) oDocumento := oEngine:RunEngine() aPaginas := oDocumento:GetPaginas() nFailures += AssertEqual( "Engine label paginas", Len( aPaginas ), 2 ) nFailures += AssertEqual( "Engine label primera pagina", Len( aPaginas[ 1 ][ "objetos" ] ), 2 ) nFailures += AssertEqual( "SendDetalle CP1252 normalizado", aPaginas[ 1 ][ "objetos" ][ 1 ][ "texto" ], cUtf8Probe ) nFailures += AssertEqual( "Engine label inicio x", aPaginas[ 1 ][ "objetos" ][ 1 ][ "x" ], 6.0 ) nFailures += AssertEqual( "Engine label inicio y", aPaginas[ 1 ][ "objetos" ][ 1 ][ "y" ], 19.0 ) nFailures += AssertEqual( "Engine label segunda pagina texto", aPaginas[ 2 ][ "objetos" ][ 1 ][ "texto" ], "Tres" ) hInputStats := oEngine:GetInputDiagnostics() nFailures += AssertEqual( "Diagnostico entrada cuenta registros", hInputStats[ "nRecords" ], 5 ) nFailures += AssertEqual( "Diagnostico entrada cuenta valores", hInputStats[ "nValues" ], 5 ) nFailures += AssertEqual( "Diagnostico entrada mide normalizacion", hInputStats[ "nNormalizeMs" ] >= 0, .T. ) nFailures += AssertEqual( "Diagnostico entrada mide acumulacion", hInputStats[ "nAccumulateMs" ] >= 0, .T. ) oEngine:End() oEngine := TLLEngine():New():Create() oEngine:SetPlantillaContent( MemoRead( cFaccli ) ) oEngine:OpenJob() nFailures += AssertEqual( "Engine faccli carga datos con campos acentuados", LoadSampleData( oEngine, cFaccliDatos, .T. ), .T. ) nFailures += AssertEqual( "Engine faccli valida campos acentuados", oEngine:ValidarDatos()[ "lOk" ], .T. ) oEngine:CloseJob() oDocumento := oEngine:RunEngine() aPaginas := oDocumento:GetPaginas() nFailures += AssertEqual( "Engine faccli genera varias paginas", Len( aPaginas ) > 1, .T. ) nFailures += AssertEqual( ; "Engine faccli informa total paginas", ; PageContainsText( aPaginas[ 1 ], "Hoja", " de " + hb_NToS( Len( aPaginas ) ) ), ; .T. ) oEngine:End() nFailures += TestDetailProjectionIR( cLabel ) RETURN nFailures FUNCTION TestDetailProjectionIR( cLabel ) LOCAL oFull := TLLEngine():New( cLabel ):Create() LOCAL oProjected := TLLEngine():New( cLabel ):Create() LOCAL oFullDocument LOCAL oProjectedDocument LOCAL cFullIR LOCAL cProjectedIR LOCAL nFailures := 0 oFull:OpenJob() oFull:SendDetalle( "LINEAS", { "NOMBRE" => "Uno", "CAMPO_NO_USADO" => Replicate( "X", 200 ) } ) oFull:SendDetalle( "LINEAS", { "NOMBRE" => "Dos", "CAMPO_NO_USADO" => Replicate( "Y", 200 ) } ) oFullDocument := oFull:RunEngine() cFullIR := hb_jsonEncode( oFullDocument:GetPaginas() ) oProjected:OpenJob() oProjected:SendDetalle( "LINEAS", { "NOMBRE" => "Uno" } ) oProjected:SendDetalle( "LINEAS", { "NOMBRE" => "Dos" } ) oProjectedDocument := oProjected:RunEngine() cProjectedIR := hb_jsonEncode( oProjectedDocument:GetPaginas() ) nFailures += AssertEqual( "IR identico sin campos de detalle no usados", cProjectedIR, cFullIR ) oFull:End() oProjected:End() RETURN nFailures FUNCTION TrimTrailingEol( cText ) DO WHILE Len( cText ) > 0 .AND. ( Right( cText, 1 ) == Chr( 13 ) .OR. Right( cText, 1 ) == Chr( 10 ) ) cText := Left( cText, Len( cText ) - 1 ) ENDDO RETURN cText FUNCTION DocumentoFirma( oDocumento ) IF ! HB_ISOBJECT( oDocumento ) RETURN "" ENDIF RETURN hb_jsonEncode( { ; "nAncho" => oDocumento:nAncho, ; "nAlto" => oDocumento:nAlto, ; "aPaginas" => oDocumento:GetPaginas() ; } ) FUNCTION Utf8EncodingProbe() RETURN Chr( 0xC3 ) + Chr( 0xA1 ) + ; Chr( 0xC3 ) + Chr( 0xA9 ) + ; Chr( 0xC3 ) + Chr( 0xAD ) + ; Chr( 0xC3 ) + Chr( 0xB3 ) + ; Chr( 0xC3 ) + Chr( 0xBA ) + " " + ; Chr( 0xC3 ) + Chr( 0xB1 ) + " " + ; Chr( 0xE2 ) + Chr( 0x82 ) + Chr( 0xAC ) FUNCTION AddJsonEncodingProbe( cJson, cProbe ) LOCAL nStart := At( "{", cJson ) IF nStart == 0 RETURN cJson ENDIF RETURN Stuff( cJson, nStart + 1, 0, hb_eol() + ' "cEncodingProbe": "' + cProbe + '",' ) FUNCTION DominusEncodingProbe( cProbe, lDocumentKind ) RETURN '{"cFormatVersion":"1.0",' + ; iif( lDocumentKind, '"cDocumentKind":"report",', "" ) + ; '"cTemplateName":"' + cProbe + '","aObjects":[]}' FUNCTION Ll12EncodingProbe( cHeader, cProbe ) RETURN cHeader + hb_eol() + ; "[Description]" + hb_eol() + ; " Text=" + cProbe + hb_eol() + ; " Units=SCM-Units" + hb_eol() + ; "[Layout]" + hb_eol() + ; " xSize=210000" + hb_eol() + ; " ySize=297000" FUNCTION LoadSampleData( oEngine, cFile, lCamposAcentuados ) LOCAL hData := { => } LOCAL hDataVar LOCAL hDetailVar LOCAL hRecord LOCAL cGroup lCamposAcentuados := iif( HB_ISLOGICAL( lCamposAcentuados ), lCamposAcentuados, .F. ) IF ! File( cFile ) RETURN .F. ENDIF hb_jsonDecode( MemoRead( cFile ), @hData ) IF ! HB_ISHASH( hData ) RETURN .F. ENDIF hDataVar := HashValue( hData, "DataVar", { => } ) IF HB_ISHASH( hDataVar ) FOR EACH cGroup IN hb_HKeys( hDataVar ) hRecord := SampleRecord( hDataVar[ cGroup ] ) IF lCamposAcentuados .AND. cGroup == "OMEM_PUBLICAS" hRecord := AcentuarCamposPublicas( hRecord ) ENDIF IF Len( hRecord ) > 0 oEngine:SendDataVar( cGroup, hRecord ) ENDIF NEXT ENDIF hDetailVar := HashValue( hData, "DetalleVar", { => } ) IF HB_ISHASH( hDetailVar ) FOR EACH cGroup IN hb_HKeys( hDetailVar ) IF ! HB_ISARRAY( hDetailVar[ cGroup ] ) LOOP ENDIF FOR EACH hRecord IN hDetailVar[ cGroup ] IF HB_ISHASH( hRecord ) oEngine:SendDetalle( cGroup, SampleRecord( hRecord ) ) ENDIF NEXT NEXT ENDIF RETURN .T. FUNCTION AcentuarCamposPublicas( hSource ) LOCAL hRecord := { => } LOCAL cField LOCAL cFieldTarget FOR EACH cField IN hb_HKeys( hSource ) cFieldTarget := cField DO CASE CASE cField == "Direccion" cFieldTarget := "Direcci" + Chr( 0xF3 ) + "n" CASE cField == "Poblacion" cFieldTarget := "Poblaci" + Chr( 0xF3 ) + "n" CASE cField == "Telefono" cFieldTarget := "Tel" + Chr( 0xE9 ) + "fono" ENDCASE hRecord[ cFieldTarget ] := hSource[ cField ] NEXT RETURN hRecord FUNCTION SampleRecord( hSource ) LOCAL hRecord := { => } LOCAL cField IF ! HB_ISHASH( hSource ) RETURN hRecord ENDIF FOR EACH cField IN hb_HKeys( hSource ) hRecord[ cField ] := SampleValue( hSource[ cField ] ) NEXT RETURN hRecord FUNCTION SampleValue( uData ) LOCAL cType LOCAL uValue LOCAL aDate IF ! HB_ISHASH( uData ) .OR. ! hb_HHasKey( uData, "valor" ) RETURN uData ENDIF cType := Lower( AllTrim( hb_ValToStr( HashValue( uData, "tipo", "" ) ) ) ) uValue := uData[ "valor" ] IF cType == "fecha" .AND. HB_ISSTRING( uValue ) aDate := hb_ATokens( uValue, "/" ) IF Len( aDate ) == 3 RETURN hb_SToD( PadL( aDate[ 3 ], 4, "0" ) + PadL( aDate[ 2 ], 2, "0" ) + PadL( aDate[ 1 ], 2, "0" ) ) ENDIF ENDIF RETURN uValue FUNCTION HashValue( hHash, cKey, uDefault ) IF HB_ISHASH( hHash ) .AND. hb_HHasKey( hHash, cKey ) RETURN hHash[ cKey ] ENDIF RETURN uDefault FUNCTION PageContainsText( hPage, cPrefix, cFragment ) LOCAL hObject LOCAL cText IF ! HB_ISHASH( hPage ) .OR. ! hb_HHasKey( hPage, "objetos" ) .OR. ! HB_ISARRAY( hPage[ "objetos" ] ) RETURN .F. ENDIF FOR EACH hObject IN hPage[ "objetos" ] IF ! HB_ISHASH( hObject ) .OR. ! hb_HHasKey( hObject, "texto" ) LOOP ENDIF cText := hb_ValToStr( hObject[ "texto" ] ) IF At( cPrefix, cText ) > 0 .AND. At( cFragment, cText ) > 0 RETURN .T. ENDIF NEXT RETURN .F. FUNCTION AssertEqual( cCaseName, uActual, uExpected ) IF HB_ISNUMERIC( uActual ) .AND. HB_ISNUMERIC( uExpected ) IF Abs( uActual - uExpected ) <= 0.000001 RETURN 0 ENDIF ELSEIF ValType( uActual ) == ValType( uExpected ) .AND. uActual == uExpected RETURN 0 ENDIF LogLine( "FAIL " + cCaseName ) LogLine( " esperado: " + ValueToString( uExpected ) ) LogLine( " actual : " + ValueToString( uActual ) ) RETURN 1 FUNCTION ValueToString( uValue ) IF uValue == NIL RETURN "NIL" ENDIF IF HB_ISSTRING( uValue ) RETURN uValue ENDIF IF HB_ISNUMERIC( uValue ) RETURN hb_NToS( uValue ) ENDIF IF HB_ISLOGICAL( uValue ) RETURN iif( uValue, ".T.", ".F." ) ENDIF IF HB_ISARRAY( uValue ) RETURN "Array(" + hb_NToS( Len( uValue ) ) + ")" ENDIF IF HB_ISHASH( uValue ) RETURN "Hash(" + hb_NToS( Len( uValue ) ) + ")" ENDIF RETURN AllTrim( hb_ValToStr( uValue ) ) PROCEDURE LogLine( cText ) OutStd( cText + hb_eol() ) RETURN PROCEDURE InstallConsoleErrorHandler() ErrorBlock( {| oError | ConsoleErrorHandler( oError ) } ) RETURN FUNCTION ConsoleErrorHandler( oError ) LOCAL nLevel OutErr( "ERROR Harbour no interactivo" + hb_eol() ) OutErr( "SubSystem : " + ValueToString( oError:SubSystem ) + hb_eol() ) OutErr( "SubCode : " + ValueToString( oError:SubCode ) + hb_eol() ) OutErr( "Description: " + ValueToString( oError:Description ) + hb_eol() ) OutErr( "Operation : " + ValueToString( oError:Operation ) + hb_eol() ) OutErr( "Pila:" + hb_eol() ) FOR nLevel := 1 TO 40 IF Empty( ProcName( nLevel ) ) EXIT ENDIF OutErr( " " + ProcName( nLevel ) + "(" + hb_NToS( ProcLine( nLevel ) ) + ")" + hb_eol() ) NEXT ErrorLevel( 1 ) QUIT RETURN NIL