UDX test harness

Use the test harness to run your UDXs in a test environment outside the runtime engine. It is useful to debug user code to collect useful statistics on the user code and to check for certain programming errors.

For complicated UDAs and UDFs, run the test harness first as it might catch errors such as buffer overruns. Always run the UDX in fenced mode first, then in unfenced mode after you debug any issues with the UDX.

For the sample UDF customername, you can run the UDF in the test harness by using the following command:
nzudxrunharness --user admin --pw password --db mydb 
--dir /nz/data.1.0 --name customername --fenced
This command runs the customername function 100 times with randomly generated data and displays output similar to the following output:
(clientmgr)  Info: admin: login successful
Selected only choice
1 - customername(VARCHAR(64000)) RETURNS INT4
Executing /nz/kit/bin/adm/udxharness -f customername_func.harness -k 
/nz/kit.6.0.B4.14104

starting execution
Elapsed time: 0m0.039s

External references
logvprint(char const*, char*)
vtable for __cxxabiv1::__class_type_info
vtable for __cxxabiv1::__si_class_type_info
operator delete[](void*)
operator delete(void*)
operator new(unsigned int)
__cxa_pure_virtual
__gxx_personality_v0
free
memcmp
sprintf
strcmp
strdup
throwError

Our UDX object used 262144 bytes (may be rounded up to nearest page 
4096)
Our UDX return value takes up 4 bytes, with 669 bytes for miscellaneous
Our UDX arguments take up 64012 bytes, with 14 bytes for miscellaneous
Our UDX state values take up 0 bytes, with 8 bytes for miscellaneous
State information may be doubled, since we need two states for merge

The first section of the output shows the possible UDFs that match customername. If there is more than one (in the case of multiple UDFs that have the same name but different arguments), the command prompts you to select which UDF to use. This command then displays some status information about the actual call that is executed, along with a starting and executing message.

If the function runs with no errors, the “External references” section of the output lists any external library functions that the function uses. Always list sprintf and throwUdxException() as they are included by the support functions, such as int32Arg(int).

The last section of the output displays estimated memory usage for the UDF.

Although the sample customername function is simple and operating correctly, assume that the UDF has a problem. The following code for the function has a deliberate error that would cause a buffer overrun when the function runs:
virtual ReturnValue evaluate()
    {
        StringArg *str = stringArg(0); 
        int lengths = str->length; 
        char *datas = str->data; 

        char* ptr = (char*)str;
        for (int i=0; i < 4000; i++)
        {
            *(ptr-i) = 5;
        }
        int32 retval = 1;
        if (lengths >= 10)
            if (memcmp("Customer A",datas,10) == 0)
            {
                 logMsg(LOG_DEBUG, "Found a match of length %d\n",
                  lengths); 
                 retval = 1;
            }
        NZ_UDX_RETURN_INT32(retval); 
}
If you have a new function, or one that you find to have an error in processing, you can compile the UDX with a debugging option, as follows:
nzudxcompile customername.cpp –o customername.o -g
Assume that this incorrect function is registered. The next step is to run it by using the test harness, as follows:
nzudxrunharness --user admin --pw password --db mydb 
--dir /nz/data.1.0 --name customername --unfenced
The output from the test harness is similar to the following output:
(clientmgr)  Info: admin: login successful
Selected only choice
1 - customername(VARCHAR(64000)) RETURNS INT4
Executing /nz/kit/bin/adm/udxharness -f customername_func.harness -k 
/nz/kit.6.0.B4.14104

starting execution
layout of overwrite structure is:
pReturnInfo
pReturnNull
returnType
numArgs
argTypes
args
argNulls
argConsts
ERROR: (After function evaluate): Mismatch after retNulls between 
bytes 9 and 999 0
Caught exception
When the test harness detects a buffer overwrite, the output displays the structure order and where the error occurred. In this case, the error occurs after returnType. To try and identify the cause of the problem, you can debug it in GDB as follows:
nzudxrunharness --user admin --pw password --db mydb 
--dir /nz/data.1.0 --name customername –-dbg

This command starts the gdb before the execution of your UDF. A good place to set a breakpoint is on the evaluate() method by typing:

(gdb) break CCustomerName::evaluate

For more information about debugging to isolate programming problems, consult the GDB documentation at http://www.gnu.org/software/gdb.