Unit-test EAF dst component

In case you are a poor PB developer still working on the dead EAF framework., here is the solution to make your life a little bit funner.

Unit-test IM

Lib List:

c:\pb_projects\testApp\src\server\testApp\pb112\integration-test\im_testApp_test.pbl;
c:\pb_projects\testApp\lib\my_client.pbd;
c:\pb_projects\testApp\lib\ext_client.pbd;
c:\pb_projects\testApp\lib\eaf_client.pbd;
c:\pb_projects\testApp\lib\my_shared.pbd;
c:\pb_projects\testApp\lib\eaf_shared.pbd;
c:\pb_projects\testApp\lib\ext_shared.pbd;
c:\pb_projects\testApp\test\tools\pbunit\pbunit.pbd;
c:\pb_projects\testApp\test\tools\pbunit\pbunitfunc.pbd;
c:\pb_projects\testApp\lib\my_eaf_ext_layer_rc.pbl;
c:\pb_projects\testApp\lib\eaf_proxies.pbd;

PBUnit test code:


//instance
n_connection icn_easerver
n_cst_interfaceservice inv_is

//setup

long ll_rc

constant string INI_FILE = "app.ini"

icn_easerver = CREATE n_connection
icn_easerver.driver = "jaguar"
icn_easerver.userID = ProfileString(INI_FILE, "EAServer", "UserID", "jagadmin")
icn_easerver.password = ProfileString(INI_FILE, "EAServer", "Password", "")
icn_easerver.options = ProfileString(INI_FILE, "EAServer", "Options", "")
icn_easerver.location = ProfileString(INI_FILE, "EAServer", "Server", "")+ ":" + ProfileString(INI_FILE, "EAServer", "Port", "")

ll_rc = icn_easerver.ConnectToServer()

IF ll_rc <> 0 THEN
fail("Connection failed: " + string(ll_rc))
return
END IF

inv_is = create n_cst_interfaceservice

inv_is.of_SetRequestor(This)
ll_rc = inv_is.setConnection(icn_EAServer)

inv_is.of_setUserID("jagadmin")
ll_rc = inv_is.setInterfaceManagerName("MyPackage/MyComponent")

// test dst without arg
long ll_rc

datastore lds_target
lds_target = create datastore

ll_rc = inv_is.registerdataset( "session_list" ,lds_target, "fullalways")

ll_rc = inv_is.retrieve("session_list" )

assert(ll_rc = 1)

assert(lds_target.rowcount() > 0)

//test dst with arg
long ll_rc

datastore lds_target
lds_target = create datastore

ll_rc = inv_is.registerdataset( "reg_activity" ,lds_target, "fullalways")
inv_is.addArgument( "reg_activity", "lastndays", 500  )

ll_rc = inv_is.retrieve("reg_activity" )

assert(ll_rc = 1)

assert(lds_target.rowcount() > 0)

Advertisements

Using PowerGen to bootstrap pbl

We are on the process of applying continuous integration to all our powerbuilder projects. One of the challenge is the classic orcascript sometimes failed in bootstrap pbls. e.g. customer exception. The interesting thing is, I can see the objects in the pbl by using yBrowser 10. but the object contains customer exception is missing from pbl when I try to look it in PowerBuilder IDE.

Anyway, PowerGen definately can save me out of this trouble. It’s slow comparing to orca because it’s checking all the depenanct when bootstrapping, but it’s stable.

Something I think PowerGen can improve in the future:

  1. Allow passing parameters into, so I can still use orca to build executable with version number. PowerGen implement this by using their version edit product to do the post build action.
  2. Work path should be dynamic, right now it’s hard-coded in gen file. I have to standardize it. I can change the *.gen file to replace those absolute path to relative one, but why couldn’t make the relative path be default? relative path is very necessary for branching.

Some other reasons for using orca besides PowerGen:

  1. to deploy EAServer component.
  2. orca import is very fast than synchronizing pbl from exported sr* file in PowerGen. This is a must-have feature to branch-merge in subversion, developers should be able to do this without PowerGen installed.

Use NotePad++ to create orca build script quickly

When creating orcascipt, usually I start from the existing PBT file which contains the huge lib list:

LibList "myapp_appl.pbl\\myapp_appl.pbl;myapp_attachment.pbl\\myapp_attachment.pbl;myapp_br.pbl\\myapp_br.pbl;myapp_casefile.pbl\\myapp_casefile.pbl;myapp_casefile_related.pbl\\myapp_casefile_related.pbl;myapp_dddw.pbl\\myapp_dddw.pbl;myapp_disciplinary_action.pbl\\myapp_disciplinary_action.pbl;myapp_licensee.pbl\\myapp_licensee.pbl;myapp_list.pbl\\myapp_list.pbl;myapp_mass_entry.pbl\\myapp_mass_entry.pbl;myapp_registration.pbl\\myapp_registration.pbl;myapp_report.pbl\\myapp_report.pbl;myapp_resource.pbl\\myapp_resource.pbl;myapp_schedule.pbl\\myapp_schedule.pbl;myapp_security.pbl\\myapp_security.pbl;myapp_ticket.pbl\\myapp_ticket.pbl;im_lls_rc_dws.pbl\\im_lls_rc_dws.pbl;im_lls_rc_rpt_dws.pbl\\im_lls_rc_rpt_dws.pbl;pies_shared.pbl\\pies_shared.pbl;reg_01.pbl\\reg_01.pbl;"

I want the orca format like this:

build executable "myapp.exe" "myapp.ico" "myapp.pbr" "yyyyyyyyyyyyyyyyyyy"

build Library "myapp_appl.pbl\myapp_appl.pbl" "" PBD
build Library "myapp_attachment.pbl\myapp_attachment.pbl" "" PBD
build Library "myapp_br.pbl\myapp_br.pbl" "" PBD
build Library "myapp_casefile.pbl\myapp_casefile.pbl" "" PBD
build Library "myapp_casefile_related.pbl\myapp_casefile_related.pbl" "" PBD
build Library "myapp_dddw.pbl\myapp_dddw.pbl" "" PBD
build Library "myapp_disciplinary_action.pbl\myapp_disciplinary_action.pbl" "" PBD
build Library "myapp_licensee.pbl\myapp_licensee.pbl" "" PBD
build Library "myapp_list.pbl\myapp_list.pbl" "" PBD
build Library "myapp_mass_entry.pbl\myapp_mass_entry.pbl" "" PBD
build Library "myapp_registration.pbl\myapp_registration.pbl" "" PBD
build Library "myapp_report.pbl\myapp_report.pbl" "" PBD
build Library "myapp_resource.pbl\myapp_resource.pbl" "" PBD
build Library "myapp_schedule.pbl\myapp_schedule.pbl" "" PBD
build Library "myapp_security.pbl\myapp_security.pbl" "" PBD
build Library "myapp_ticket.pbl\myapp_ticket.pbl" "" PBD
build Library "im_lls_rc_dws.pbl\im_lls_rc_dws.pbl" "" PBD
build Library "im_lls_rc_rpt_dws.pbl\im_lls_rc_rpt_dws.pbl" "" PBD
build Library "pies_shared.pbl\pies_shared.pbl" "" PBD
build Library "reg_01.pbl\reg_01.pbl" "" PBD

Here is how I did it in minutes of work, using NotePad++ relace with regexp:

  1. Replace step 1, this is easy, replace all \\ with \, and ‘;’ with “\n”
  2. Replace step 2, using regexp, replace all
    ^(.*)
    with
    build Library “\1” “” PBD
  3. Done.

Notepad++ reference: http://notepad-plus.sourceforge.net/uk/regExpList.php

PowerUnit changed to NAnt auto-build

Sourceforge stats shown that PowerUnit has not been updated for 2years, this is wrong! I’m currently still actively playing it. The recent changes including:

  1. Using NAnt auto-build each release. The forth part of version number is subversion revision. The lattest one is 119. The subversion repository is at https://powerunit.svn.sourceforge.net/svnroot/powerunit/
  2. Display PB context version of current PBUnit. Be aware that PB context version must match with the test target. If your target is different, you need to rebuild it, either use NAnt, or in your PB IDE.pbunit_ver
  3. I am using PBScc as my current subversion client, tried PushOK for awhile, it’s OK. Comparing this PBSCC, it’s almost same as old PB dev style.
    PBSCC needs a middle area as the buffer/swap between dev machine to source repository, I think some damon process is monitoring this buffer/swap folder whenver checkin happens, then commit the changes to repo behind the scene. This left the problem of my main src folder shown un-commint-changes icon, doing a diff, the base still no showing the new changes commint through PBSCC, force a update, it said finished a merge, even the src file actually not changed at all.
    pbunit_pbscc_folderpbunit_pbscc_workspace

Embed Autodeploy PB component task to CruiseControl

Problem: Any team member can deploy PB component to EAserver from PB IDE, even if they have local code not checked in, and it’s not traceable also (not in EAServer log!). We don’t know who and when touched those component on server.

We tried to put version info in the comments field of component, but it’s not guaranteed. Developer still might forget. If EAServer administrator didn’t version that point, we couldn’t rollback to certain standpoint.

Solution: Auto-deploy from CC.net build task, which is triggered by check in. Ideally should run a test project before deploy.

Similar idea from some websphere developer. We should archieve the ear file, but the orcascript alone can generate it, so call an easerver export instead.

Orcascript command:

build project PBL_NAME PROJECT_NAME SERVER_HOST PORT_NUMBER

Don’t know how to pass userid/password to this orca command. Had to add easerver profile to CC.net machine.

Ant task:

<property name="JAGUAR" value="C:\Program Files\Sybase\EAServer6\bin" />
 <target name="export_package" depends="">
 <echo message="exporting package ..." />
 <!-- <jag_export entity="Package:My_Package" /> -->
 <delete file="jar\My_Package.jar" />
 <!-- nant change executable to program -->
 <exec executable="${JAGUAR}\jagtool.bat" >
 <arg line="-server easdevSecure -host easdev -port 9100  -user jagadmin -password pass export -dir jar/ Package:My_Package" />
 </exec>
 </target>

PB read version number from exe

This is for pB10.5 or later, Unicode style.

FUNCTION ulong GetFileVersionInfoSizeW  &
( REF string lpFilename, REF ulong lpdwHandle ) &
LIBRARY “version.dll”

FUNCTION integer GetFileVersionInfoW &
( REF string lpFilename, REF ulong lpdwHandle, ulong dwLen, &
REF string lpData )  &
LIBRARY “version.dll”

FUNCTION boolean VerQueryValueW &
( REF string lpBlock, string lpSubBlock, REF long lpBuffer, &
REF uint puLen )  &
LIBRARY “version.dll”

SUBROUTINE CopyMemoryA &
( REF string d, long s, long l )  &
LIBRARY “kernel32.dll”  &
ALIAS FOR RtlMoveMemory

FUNCTION ulong GetModuleFileName (ulong hinstModule, ref string lpszPath, ulong cchPath )  &
LIBRARY “KERNEL32.DLL” &
ALIAS FOR “GetModuleFileNameA;ansi”  // ;ansi  required for PB10 or later

// function of_get_version()
ulong  dwHandle, dwLength
string ls_Buff, ls_key
uint   lui_length
long   ll_pointer
string ls_filename  
integer li_rc
string  ls_result = ‘?’
string ls_EXE_FILE_NAME
String ls_fullpath
ulong lul_handle, lul_length = 512

lul_handle = handle( getapplication() )

If lul_handle = 0 Then //IDE MODE
RETURN ‘[IDE mode]’
End if

// running from EXE
ls_fullpath=space(lul_length)
GetModuleFilename( lul_handle, ls_fullpath, lul_length )

//ls_filename = GetCurrentDirectory ( ) + “\” + ls_EXE_FILE_NAME
ls_filename = ls_fullpath

dwLength = GetFileVersionInfoSizeW( ls_filename, dwHandle )
IF dwLength <= 0 THEN RETURN ls_result END IF ls_Buff = Space( dwLength ) li_rc = GetFileVersionInfoW( ls_filename, dwHandle, dwLength, ls_Buff ) IF li_rc = 0 THEN RETURN ls_result END IF // the strange numbers below represents the country and language // of the version resource. ls_key = "\StringFileInfo40904e4\FileVersion" IF NOT VerQueryValueW( ls_buff, ls_key, ll_pointer, lui_length ) OR & lui_length <= 0 THEN ls_result = "?" ELSE ls_result = Space( lui_length ) CopyMemoryA( ls_result, ll_pointer, lui_length*2 ) // unicode END IF return ls_result [/sourcecode] More to investigate: 1. How to deal with component on EAServer? Couldn't find solution from WCF architecture. Don't we care the version number of a remote service?

workdir setup in PB+PuskOK+SVN+CC.net mode

pb_dir

Ideas:

  1. Move all source file into src folder, keep pbw and pbt file in same level, otherwise PUSHOK plugin will add relative path into pbg files, which is wrong, orca will fail due to this.
  2. Add pbl into ignore list, this file keep changing and we don’t want it in repository.
  3. Create 2 build script, one for incremental build , another for full build with delete pbl, import/migrate and create exe.
  4. dist folder for distribution, should keep zip file for executable and pbls. When new member join in, after GLV from svn repository, should extra the pbl from the zip file in this folder.
  5. orca can build in offline mode, because svn will keep all the sr* file updated.
    Offline mode is only available in PB10 or above.

    start session
    scc set connect property logfile "buildfromsource.log"
    
    ;**********************************************************************
    ; connect mode
    ; read scc info from workspace
    ;**********************************************************************
    ;SCC get connect properties "pbunit.pbw" 
    ;scc connect 
    ;scc set target "pbunitgui.pbt"  OUTOFDATE 
    ;scc refresh target migrate
    
    ;**********************************************************************
    ; offline mode
    ; sr* file should already in the src folder done by svn
    ;**********************************************************************
    scc connect offline
    scc set target "pbunitgui.pbt"  IMPORTONLY
    scc refresh target migrate  
    
    scc close 
    ...build exe...