Unit Testing Private Static Methods With Primitive Array Arguments

When writing unit tests to cover your entire program you will undoubtedly come across the need to test private methods.  There are arguments that these methods should be tested via integration tests, but there are sometimes when it makes more sense to test all of the permutations in a unit test. This can be achieved using reflection in Java JUnit tests.

What is a little tricky, and was not completely obvious, was how to use reflection to test a private static method that accepted an array of primitives.  Following is a simple example, with explainations in the comments.

Note, this code will not run as it, you would need to transpose it into a valid JUnit test class to bypass the IllegalAccessException.

Class with private method that you want to test:

public class ByteCounter {
    private static int countByteValue(byte[] arr) {
        int retVal = 0;
        for (int i = 0; i < arr.length; i++) {
            retVal += (int) arr[i];
        }
        return retVal;
    }
}

Unit test code:

import java.lang.reflect.Method;

public class StaticArrayReflectionTest {

    public static void main(String[] args) throws Exception {
        byte[] arr = new byte[] { 1, 2, 3, 4 };

        // Get a Class instance of the class to be tested
        Class<ByteCounter> byteCounterClazz = ByteCounter.class;

        /*
         * Get a Method instance for the method to be tested. The part to take
         * note of is how to get a Class instance of a array of primitives.
         */
        Method countByteValueMethod = byteCounterClazz.getDeclaredMethod("countByteValue",
            new Class[] { byte[].class });

        /*
         *
         * Invoke the Method instance passing in the arr argument.
         *
         * Take note that the first argument of invoke is 'null' as there is no object
         * instance on which to invoke the method since the method in question is
         * static. Also notice how the byte array is passed in, wrapped in an Object[]
         */
        countByteValueMethod.invoke(null, new Object[] { arr });
    }
}

One-Liner for Converting CRLF to LF in Text Files

If you have text files created under DOS/Windows and need to convert the CRLF (carriage return and line feed) characters to LF (line feed) character, here is a quick one-liner.

cat file.txt | perl -ne 's/\x0D\x0A/\x0A/g; print' > file.txt.mod

You can also use dos2unix, however, especially under Cygwin I have seen dos2unix fail without giving any meaningful information about why it was unable to complete the task.  In that case, you can just do it by hand. 

Configuring Eclipse to Replace Tabs with Spaces for Indentation

Following are two basic settings (I believe that there are other language specific, C++ for instance, settings as well).

 For Java:

Window->Preferences->Java->Code Style->Formatter->
Click on ‘New’ to create a new profile and select the profile that you want to copy
Then click ‘Edit’ and select ‘Spaces Only’ from the ‘Tab Policy’ dropdown.

You can further set the indentation and tab size.

For default text editor:

Window->Preferences->General->Editors->Text Editors->Insert spaces for tabs

Parsing Command Line Arguments with getopt in Bash

When writing utility scripts in Bash it is tempting to simply pass positional arguments, use $1, $2, etc. and be done with it.  However if you want to either share this utility with other members of your team and/or incorporate it into your system, it makes sense to implement your command line argument parsing in a more flexible and maintainable manner.

Using getopt you can very easily pass a variety of command line options and arguments.

Following is a link to a GitHub Gist with an example that illustrates the implementation of flags, options or arguments with values and long option names.

getopt-example.sh

Passing an Array as an Argument to a Bash Function

If you want to pass an array of items to a bash function, the simple answer is that you need to pass the expanded values.  That means that you can pass the data as a quoted value, assuming that the elements are whitespace delimited, or you can pass it as a string and then split it using an updated IFS (Internal Field Separator) inside the function.

Following is an example of taking the output of a Hive query (a single column that is separated by new lines), wrapping it in quotes and passing it as a single value to the function.

#!/bin/bash

#
# This function will accept the expanded elements of the array
#
function foo() {
# Loop through elements in the first argument passed.
   # In this case, each is separated by whitespace so we do
   # not need to change the IFS
   for i in $1
   do
      echo "i = $i"
   done
}

# Dynamically build our hive query
HIVE_QRY="use somedb; select some_column from some_table;"

# Dynamically build the hive command to execute
CMD="hive -e '$HIVE_QRY'"

# Execute the hive query in a subshell and store the result in
# the 'QRY_RETVAL' variable
QRY_RETVAL=$(eval $CMD)

# Call the foo method and pass it the output of the query, /QUOTED/
# so that it will be passed as a single argument and not a series
# of arguments for each row returned by the query
foo "${QRY_RETVAL}"

Vim Search and Replacing with Backreferences

It is often helpful to write search and replace commands that save segments of the matched text to use in the replacement string.

Source text:

This is some text (we want to change) with a phone number (301) 555-1234.
We want to remove the parenthesis, but only from the phone number string.

In this example we have a text file that has a phone number in it and we want to remove the parenthesis that surround ONLY the area code in the phone number, plus the trailing space and replace it with the aread code plus a trailing “-“.

Following is the search and replace command. The forward slashes are separators in the search command.  They will be omitted in the full explanation below:

:1,%s/(\([0-9]\+\))\s/\1-/g

Here is it explained:

:1,%s

Tells, vi to execute the search and replace command from line 1 to the end of the document

(\([0-9]\+\))\s

The regex including the backreference that will find the area code including the parenthesis and a trailing space.  The \(  and \) parenthesis wrap the numerical part of the string that we are trying to save and mark it as a backreference.  The \+ indicates that we one one or more of the numerical characters (the plus char must be escaped).  The \s indicates a whitespace character the we also want to match.

\1-

The characters that we want to use to replace what we have found.  The \1 indicates we want to use the first backreference that was matched followed by a ‘-‘ character. 

g

Tells, vi to execute the search and replace on all occurances found in a line.

Removing the Last Token From a String in Bash with awk

Let’s say that you have some number of files for which you want to create a containing directory that is named with all but the last token of the file name, and you want to remove just the last token to create the name of the directory.

Much easier to explain with an example.  Given this list of files:

ls -1
foo_10_10_sometrash
foo_1_sometrash
foo_2_sometrash
foo_3_sometrash
foo_4_sometrash
foo_5_5_sometrash
foo_5_sometrash
foo_6_6_sometrash
foo_7_7_sometrash
foo_8_8_sometrash
foo_9_9_sometrash

You want to create a directory for each of the files as follows:

foo_5_sometrash should have a directory named foo_5.

Further, let’s assume that you have thousands, or hundreds of thousands of files.  In that case doing it via a script while you get a cup of coffee is the preferred solution.

The work will be done within a for i in loop iterating over the output from ls with a nested awk command.

for i in `ls -1`; do DIRNAME=$(echo $i | awk -F_ '{$NF=""; print $0}' | sed 's/ /_/g' | sed 's/_$//g'); mkdir $DIRNAME; done

Here is the command broken down:

DIRNAME=$(....)

will set the var $DIRNAME to the result of the code within the parenthesis.

awk -F_ '{$NF=""; print $0}

will set the field separator to a ‘_’, the character on which you will be ‘splitting’ your string.  $NF="" will set the last field to an empty string and then the print $0 will print the entire input line.

The following sed commands will replace the spaces generated by the awk command with the original separators, ‘_’, and then remove the spurious, trailing ‘_’.