Hi,

After reading through GTest, and the JSP/Servlet-Gtest.xml, none of the
tests set the "exactMatch" property to true to do whitespace comparison
between the response from the server, and the contents of the
goldenfile.  This patch, will make GTest do a byte for byte comparison
of the response and goldenfile.  If any length or byte differeces
appear, it will dump a hex representation (ascii on the right side, hex
on the left) to help the test writer figure out what's wrong.  Make's
it easier in my opinion anyway :).


I plan to start going through and correcting the whitespace issues as 
I come across them, so there will probably be more patches to come down
the pipe.

Anyway, attached is the patch to GTest (GTest.patch.txt) as well as
sample output (sample.txt) of what this code produces when exactMatch is
set to true.

Anyone care to comment?

Thanks,

-rl


Index: GTest.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-watchdog-4.0/src/tools/org/apache/tomcat/task/GTest.java,v
retrieving revision 1.3
diff -u -r1.3 GTest.java
--- GTest.java  2001/09/28 04:09:56     1.3
+++ GTest.java  2001/11/19 21:36:00
@@ -15,6 +15,11 @@
 
 // derived from Jsp
 public class GTest extends Task {
+
+    private static final String ZEROS = "00000000";
+    private static final int SHORTPADSIZE = 4;
+    private static final int BYTEPADSIZE = 2;
+
     String prefix="http://localhost:8080/test";;
     String host="localhost";
     int port=8080;
@@ -376,9 +381,9 @@
        boolean cmp=true;
        
        if(exactMatch)
-           cmp=compare(responseBody, expResult.toString() );
+           cmp=compare(responseBody.getBytes(), expResult.toString().getBytes() );
        else
-           cmp=compareWeek( responseBody, expResult.toString());
+           cmp=compareWeak( responseBody, expResult.toString());
        
        if( cmp  != testCondition ) {
            responseStatus = false;
@@ -521,30 +526,200 @@
         }
     }
 
+    /*
+     * <code>compare</code> compares the two byte arrays passed
+     * in to verify that the lengths of the arrays are equal, and
+     * that the content of the two arrays, byte for byte are equal.
+     *
+     * @param fromServer a <code>byte[]</code> value
+     * @param fromGoldenFile a <code>byte[]</code> value
+     * @return <code>boolean</code> true if equal, otherwise false
+     */
+    private boolean compare( byte[] fromServer, byte[] fromGoldenFile ) {
+        if ( fromServer == null || fromGoldenFile == null ) {
+            return false;
+        }   
+
+        /*
+         * Check to see that the respose and golden file lengths
+         * are equal.  If they are not, dump the hex and don't
+         * bother comparing the bytes.  If they are equal,
+         * iterate through the byte arrays and compare each byte.
+         * If the bytes don't match, dump the hex representation
+         * of the server response and the goldenfile and return
+         * false.
+         */
+
+        if ( fromServer.length != fromGoldenFile.length ) {
+            StringBuffer sb = new StringBuffer( 50 );
+            sb.append( "Response and golden file lengths do not match!\n" );
+            sb.append( "Server response length: " );
+            sb.append( fromServer.length );
+            sb.append( "\nGoldenfile length: " );
+            sb.append( fromGoldenFile.length );
+            System.out.println( sb.toString() );
+            sb = null;
+            // dump the hex representation of the byte arrays
+            dumpHex( fromServer, fromGoldenFile );
+
+            return false;
+
+        } else {
+
+            int i = 0;
+            int j = 0;
+
+            while ( ( i < fromServer.length ) && ( j < fromGoldenFile.length ) ) {
+                if ( fromServer[ i ] != fromGoldenFile[ j ] ) {
+                    System.out.println( "Error at position " + ( i + 1 ) );
 
-    // Compare the actual result and the expected result.
-    private boolean compare(String str1, String str2) {
-       //System.out.println("In compare");
-       if ( str1==null || str2==null) return false;
-       if ( str1.length() != str2.length() ) {
-           System.out.println("Wrong size " + str1.length() +" " + str2.length() );
-           return false;
-       }
-       
-        for(int i=0; i<str1.length() ; i++ ) {
-            if (str1.charAt( i ) != str2.charAt( i ) ) {
-               System.out.println("Error at " + i  + " " + str1.charAt(1) +
-                                  str2.charAt(i));
-                return false;
+                    // dump the hex representation of the byte arrays
+                    dumpHex( fromServer, fromGoldenFile );
+
+                    return false;
+                }
+
+                i++;
+                j++;
+            }
+        }
+
+        return true;
+    }
+
+    /*
+     * <code>dumpHex</code> helper method to dump formatted
+     * hex output of the server response and the goldenfile.
+     *
+     * @param serverResponse a <code>byte[]</code> value
+     * @param goldenFile a <code>byte[]</code> value
+     */
+    private void dumpHex( byte[] serverResponse, byte[] goldenFile ) {
+        StringBuffer outBuf = new StringBuffer( ( serverResponse.length + 
+goldenFile.length ) * 2 );
+
+        String fromServerString = getHexValue( serverResponse, 0, 
+serverResponse.length );
+        String fromGoldenFileString = getHexValue( goldenFile, 0, goldenFile.length );
+
+        outBuf.append( "Hex dump of server response and goldenfile below.\n\n### 
+RESPONSE FROM SERVER ###\n" );
+        outBuf.append( "----------------------------\n" );
+        outBuf.append( fromServerString );
+        outBuf.append( "\n\n### GOLDEN FILE ###\n" );
+        outBuf.append( "-------------------\n" );
+        outBuf.append( fromGoldenFileString );
+        outBuf.append( "\n\n### END OF DUMP ###\n" );
+
+        System.out.println( outBuf.toString() );
+
+    }
+
+    /*
+     * <code>getHexValue</code> displays a formatted hex
+     * representation of the passed byte array.  It also
+     * allows for only a specified offset and length of 
+     * a particular array to be returned.
+     *
+     * @param bytes <code>byte[]</code> array to process.
+     * @param pos <code>int</code> specifies offset to begin processing.
+     * @param len <code>int</code> specifies the number of bytes to process.
+     * @return <code>String</code> formatted hex representation of processed 
+     *         array.
+     */
+    private String getHexValue( byte[] bytes, int pos, int len ) {
+        StringBuffer outBuf = new StringBuffer( bytes.length * 2 );
+        int bytesPerLine = 36;
+        int cnt = 1;
+        int groups = 4;
+        int curPos = pos;
+        int linePos = 1;
+        boolean displayOffset = true;
+
+        while ( len-- > 0 ) {
+            if ( displayOffset ) {
+
+                outBuf.append( "\n" + paddedHexString( pos, SHORTPADSIZE,
+                                                       true ) + ": " );
+                displayOffset = false;
+            }
+
+            outBuf.append(
+                paddedHexString( ( int ) bytes[ pos ], BYTEPADSIZE, false ) );
+            linePos += 2;  // Byte is padded to 2 characters
+
+            if ( ( cnt % 4 ) == 0 ) {
+                outBuf.append( " " );
+                linePos++;
+            }
+
+            // Now display the characters that are printable
+            if ( ( cnt % ( groups * 4 ) ) == 0 ) {
+                outBuf.append( " " );
+
+                while ( curPos <= pos ) {
+                    if ( !Character.isWhitespace( ( char ) bytes[ curPos ] ) ) {
+                        outBuf.append( ( char ) bytes[ curPos ] );
+                    } else {
+                        outBuf.append( "." );
+                    }
+
+                    curPos++;
+                }
+
+                curPos = pos + 1;
+                linePos = 1;
+                displayOffset = true;
             }
+
+            cnt++;
+            pos++;
+        }
+
+        // pad out the line with spaces
+        while ( linePos++ <= bytesPerLine ) {
+            outBuf.append( " " );
         }
-       return true;
+
+        outBuf.append( " " );
+        // Now display the printable characters for the trailing bytes
+        while ( curPos < pos ) {
+            if ( !Character.isWhitespace( ( char ) bytes[ curPos ] ) ) {
+                outBuf.append( ( char ) bytes[ curPos ] );
+            } else {
+                outBuf.append( "." );
+            }
+
+            curPos++;
+        }
+
+        return outBuf.toString();
+    }
+
+    /*
+     * <code>paddedHexString</code> pads the passed value
+     * based on the specified wordsize and the value of the
+     * prefixFlag.
+     *
+     * @param val an <code>int</code> value
+     * @param wordsize an <code>int</code> value
+     * @param prefixFlag a <code>boolean</code> value
+     * @return a <code>String</code> value
+     */
+    private String paddedHexString( int val, int wordsize,
+                                    boolean prefixFlag ) {
+
+        String prefix = prefixFlag ? "0x" : "" ;
+        String hexVal = Integer.toHexString( val );
+
+        if ( hexVal.length() > wordsize )
+            hexVal = hexVal.substring( hexVal.length() - wordsize );
+
+        return ( prefix + ( wordsize > hexVal.length() ?
+                            ZEROS.substring( 0, wordsize - hexVal.length() ) : "" ) + 
+hexVal );
     }
 
     // Compare the actual result and the expected result.
     // Original compare - ignores spaces ( because most
     // golden files are wrong !)
-    private boolean compareWeek(String str1, String str2) {
+    private boolean compareWeak(String str1, String str2) {
        //System.out.println("In compareWeek");
        if ( str1==null || str2==null) return false;
        
[java]     [gtest] Response and golden file lengths do not match!
[java]     [gtest] Server response length: 124
[java]     [gtest] Goldenfile length: 114
[java]     [gtest] Hex dump of server response and goldenfile below.
[java]     [gtest] 
[java]     [gtest] ### RESPONSE FROM SERVER ###
[java]     [gtest] ----------------------------
[java]     [gtest] 
[java]     [gtest] 0x0000: 3c68746d 6c3e0d0a 3c746974 6c653e70  <html>..<title>p
[java]     [gtest] 0x0010: 6f736974 69766542 6f647945 78697374  ositiveBodyExist
[java]     [gtest] 0x0020: 733c2f74 69746c65 3e0d0a3c 626f6479  s</title>..<body
[java]     [gtest] 0x0030: 3e0d0a0d 0a3c212d 2d204465 636c6172  >....<!--.Declar
[java]     [gtest] 0x0040: 696e6720 74686520 6265616e 20776974  ing.the.bean.wit
[java]     [gtest] 0x0050: 6820626f 6479202d 2d3e0d0a 0d0a0d0a  h.body.-->......
[java]     [gtest] 0x0060: 0d0a4150 504c450d 0a3c2f62 6f64793e  ..APPLE..</body>
[java]     [gtest] 0x0070: 0d0a3c2f 68746d6c 3e200d0a           ..</html>...
[java]     [gtest] 
[java]     [gtest] ### GOLDEN FILE ###
[java]     [gtest] -------------------
[java]     [gtest] 
[java]     [gtest] 0x0000: 3c68746d 6c3e0a3c 7469746c 653e706f  <html>.<title>po
[java]     [gtest] 0x0010: 73697469 7665426f 64794578 69737473  sitiveBodyExists
[java]     [gtest] 0x0020: 3c2f7469 746c653e 0a3c626f 64793e0a  </title>.<body>.
[java]     [gtest] 0x0030: 0a3c212d 2d204465 636c6172 696e6720  .<!--.Declaring.
[java]     [gtest] 0x0040: 74686520 6265616e 20776974 6820626f  the.bean.with.bo
[java]     [gtest] 0x0050: 6479202d 2d3e0a0a 0a0a4150 504c450a  dy.-->....APPLE.
[java]     [gtest] 0x0060: 0a3c2f62 6f64793e 0a3c2f68 746d6c3e  .</body>.</html>
[java]     [gtest] 0x0070: 200a                                 ..
[java]     [gtest] 
[java]     [gtest] ### END OF DUMP ###

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to