3

First, I know the Title is a bit ambiguous. Actually I don't know how to write it better!

Second, I will describe the problem.

Situation:

I am practicing on an online judge (OJ), so in case of wrong output, the OJ shows me the test case which makes my code to fail. Normally, I can copy my code and paste it into Eclipse, then call my function with that test case and debug my code.

But the problem when the test case is a multiple calls for my function (Like testing an enhanced version of a priority queue), let's assume there were n calls till the fail of the code. So to debug the code, I will have to call the function say n times! Which is not logical!

Function the OJ will call:

public void enqueue (int value)
{
    // implementation
}
public int dequeue ()
{
    // implementation
}

Test case makes the code to fail:

Last executed input: enqueue(5, 3), enqueue(51, 60), enqueue(0, 14), enqueue(364, 16),... dequeue(),...

Action:

I need a way to call the function with an array of test cases in order to be able to debug the code.

OR

By some way call the function with its parameter directly from the string. Something like invoke("enqueue(5, 3)");

Ahmed Hamdy
  • 2,547
  • 1
  • 17
  • 23

1 Answers1

1

After some investigation, I found a way to do the Action I need by using Java Reflection Also a helpful thread What is reflection and why is it useful?

I managed to develop a tool, here you are the steps:

  1. Copy the test case in a String
  2. Split the string on each function call
  3. Remove the function name from each call, and store them in array of String in order.
  4. Split the parameter
  5. Now I have 2 arrays of integers for param1 and param2, and an array of String for invokations

I used Reflection in order to be able to call the methods from a string of calls, inside a for loop.

Then we have this

public class Test
{
    public static void main(String[] args)
    {
        String testCase = "enqueue(5, 3), enqueue(51, 60), enqueue(0, 14), enqueue(364, 16), dequeue()";
        // Prepare parameters and invocations
        int[] param1; // assuming it is ready
        int[] param2; // assuming it is ready
        String[] calls; // assuming it is ready

        try
        {
            Class calledClass = Class.forName("OJ.Prob3");
            Method calledMethod1 = calledClass.getDeclaredMethod("enqueue", String.class, int.class);
            Method calledMethod2 = calledClass.getDeclaredMethod("dequeue", null);
            for (int i = 0 ; i < calls.length ; i++)
            {
                if (calls[i].equalsIgnoreCase("enqueue"))
                    calledMethod1.invoke(calledClass.newInstance(), param[i], param2[i]);
                else if (calls[i].equalsIgnoreCase("dequeue"))
                    calledMethod2.invoke(calledClass.newInstance())
            }
        } catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        } catch (NoSuchMethodException e)
        {
            e.printStackTrace();
        } catch (SecurityException e)
        {
            e.printStackTrace();
        } catch (IllegalAccessException e)
        {
            e.printStackTrace();
        } catch (IllegalArgumentException e)
        {
            e.printStackTrace();
        } catch (InvocationTargetException e)
        {
            e.printStackTrace();
        }
    }
}

I already tested this solution and it works really very smooth, but please if anyone has a better solution, you will be more than welcome.

I will finalize the code and make it something like a tool, and I will post it soon, in order to make everybody's life easier debugging the online judges test cases.

Update:
You can do the same for the static methods, just remove .newInstance() from calledMethod1.invoke(calledClass.newInstance(), param[i], param2[i]); to something like calledMethod1.invoke(calledClass, param[i], param2[i]);

Community
  • 1
  • 1
Ahmed Hamdy
  • 2,547
  • 1
  • 17
  • 23
  • Why don't you just call `enqueue(5, 3);` and the others? What does this add? You still type it out, except now it also requires parsing and reflection to be invoked. – Jeroen Vannevel May 24 '14 at 22:55
  • @JeroenVannevel Can you please tell me how? Because you are right, I tried to do it the way you say but I can't figure it out... – Ahmed Hamdy May 24 '14 at 22:56
  • Oh okay, I figured out what you mean. Your code is very confusing because it doesn't show any assert statements (or even any kind of output for visual inspection) and the `testCase` string made it look like it was part of the program. Am I correct when I say that you parse `testCase` instead of manually adding the values? – Jeroen Vannevel May 24 '14 at 23:04
  • @JeroenVannevel Yes, I parsed it. The main problem is I receive the `testCase` string from the **online judge** like `TopCoder` and What I want is to check the same case on my local machine in order to be able to debug it. – Ahmed Hamdy May 24 '14 at 23:09