Everyware™ Software Framework

<<Previous     Quickstart     Next>>

PART 3. ESF CODE EXAMPLES
Testing

 

Example

·         Overview

·         Prerequisites

·         Junit Testing

·         Manual Testing

Example

 

Overview

This howto shows some mechanisms for testing and running test code.

 

In this example you will learn how to:

           

Prerequisites

 

Junit Testing

Before we can begin remote debugging we need something to debug.  Start by creating a project with the following basic configuration

 

 

Below is the simple Service API:

 

package com.esf.example.testing.service;

 

 

public interface ITestingExampleService {

 

      public static final String SERVICE_NAME = ITestingExampleService.class.getName();

 

      public int add(int x, int y);

     

      public int subtract(int x, int y);

     

      public int multiply(int x, int y);

     

      public int divide(int x, int y);

}

 

 

Below is the Activator code for this project.

 

package com.esf.example.testing.bundle;

 

import org.eclipse.soda.sat.core.framework.BaseBundleActivator;

 

import com.esf.core.logger.service.IEsfLoggerService;

import com.esf.example.testing.TestingExample;

import com.esf.example.testing.service.ITestingExampleService;

 

public class Activator extends BaseBundleActivator {

 

      TestingExample testingExample = null;

     

      public void activate() {

            testingExample = new TestingExample();

            testingExample.bind(getIEsfLoggerService());

            addExportedService(ITestingExampleService.SERVICE_NAME, testingExample, null);

      }

     

      public void deactivate() {

            testingExample.unbind();

            testingExample = null;

      }

     

      private IEsfLoggerService getIEsfLoggerService() {

            return (IEsfLoggerService) getImportedService(IEsfLoggerService.SERVICE_NAME);

      }

     

      protected String[] getImportedServiceNames() {

            return new String[] {

                  IEsfLoggerService.SERVICE_NAME

            };

      }

}

 

This is a pretty standard and simple Activator.  Note we are exporting the ITestingExampleService to OSGi.  Now we can look at the main implementation class.  This is shown below.

 

package com.esf.example.testing;

 

import com.esf.core.logger.service.IEsfLoggerService;

import com.esf.example.testing.service.ITestingExampleService;

 

public class TestingExample implements ITestingExampleService {

 

      private static final String LABEL = "com.esf.example.testing.TestingExample: ";

     

      private IEsfLoggerService esfLoggerService;

     

      public void bind(IEsfLoggerService esfLoggerService) {

            this.esfLoggerService = esfLoggerService;

      }

     

      public void unbind() {

            esfLoggerService = null;

      }

     

      public int add(int x, int y) {

            esfLoggerService.logDebug(LABEL + "adding - (" + x + " + " + y + " which equals " + (x+y));

            return x+y;

      }

     

      public int subtract(int x, int y) {

            esfLoggerService.logDebug(LABEL + "subtracting - (" + x + " - " + y + " which equals " + (x-y));

            return x+y;

      }

     

      public int multiply(int x, int y) {

            esfLoggerService.logDebug(LABEL + "multiplying - (" + x + " * " + y + " which equals " + (x-y));

            return x*y;

      }

     

      public int divide(int x, int y) {

            esfLoggerService.logDebug(LABEL + "dividing - (" + x + " / " + y + " which equals " + (x-y));

            return x/y;

      }

}

 

This is a simple class with the standard bind() and unbind() methods.  We also implement the ITestingExampleService here.  Note there is an intentional bug in this class that we will find later with junit.

 

Note once the class is fully written you must remember to export the package with our new service, set the Activator, and update the manifest with the proper dependencies.  It is easy to forget these steps.  This is shown if figures one, two, and three.

 

Figure 1 Exporting the Service API Package

 

Figure 2 Adding the Activator to the Manifest

 

Figure 3 Adding the Required Dependencies to the Manifest

 

This bundle will not do anything on its own.  It is simply a service now capable of being used by other components.  But, in this case we are going to write a test case for the bundle.  Really we should’ve done this before writing the implementation code.  This is the basic information on this bundle.

 

 

Creating the Junit test is a lot like a standard bundle.  However, there are some differences.  Let’s start with the JunitExample class.

 

package com.esf.example.testing.junit;

 

import junit.framework.Assert;

 

import org.apache.felix.ipojo.junit4osgi.OSGiTestCase;

import org.osgi.framework.ServiceReference;

 

import com.esf.example.testing.service.ITestingExampleService;

 

public class JunitExample extends OSGiTestCase {

 

      private ITestingExampleService testingExampleService;

     

      protected void setUp() throws Exception {

            super.setUp();

           

            ServiceReference ref = context.getServiceReference(ITestingExampleService.SERVICE_NAME);

            assertNotNull("ITestingExampleService is not available", ref);

            testingExampleService = (ITestingExampleService) context.getService(ref);

            assertNotNull("ITestingExampleService implementation is not available", testingExampleService);

      }

     

      protected void tearDown() throws Exception {

            super.tearDown();

            testingExampleService = null;

      }

     

      public void testAddition() {

            Assert.assertEquals(10, testingExampleService.add(5, 5));

            Assert.assertEquals(0, testingExampleService.add(-5, 5));

            Assert.assertEquals(10, testingExampleService.add(0, 10));

            Assert.assertEquals(3, testingExampleService.add(1, 2));

            Assert.assertEquals(10000, testingExampleService.add(20000, -10000));

      }

     

      public void testSubtraction() {

            Assert.assertEquals(0, testingExampleService.subtract(5, 5));

            Assert.assertEquals(-10, testingExampleService.subtract(-5, 5));

            Assert.assertEquals(-10, testingExampleService.subtract(0, 10));

            Assert.assertEquals(-1, testingExampleService.subtract(1, 2));

            Assert.assertEquals(30000, testingExampleService.subtract(20000, -10000));

      }

     

      public void testMultiplication() {

            Assert.assertEquals(25, testingExampleService.multiply(5, 5));

            Assert.assertEquals(-25, testingExampleService.multiply(-5, 5));

            Assert.assertEquals(0, testingExampleService.multiply(0, 10));

            Assert.assertEquals(2, testingExampleService.multiply(1, 2));

            Assert.assertEquals(-200000000, testingExampleService.multiply(20000, -10000));

      }

     

      public void testDivision() {

            Assert.assertEquals(1, testingExampleService.divide(5, 5));

            Assert.assertEquals(-1, testingExampleService.divide(-5, 5));

            Assert.assertEquals(0, testingExampleService.divide(0, 10));

            Assert.assertEquals(0, testingExampleService.divide(1, 2));

            Assert.assertEquals(-2, testingExampleService.divide(20000, -10000));

      }

}

 

Note that we extend the OSGiTestCase.  We also implement setUp() and tearDown() methods.  These are used like standard Junit test setUp() and tearDown() methods.  But, you’ll note this is where we use the ServiceReference class to ‘grab’ a reference to the service we are testing.  We do not use an Activator as we would for a standard bundle.  We use test*() methods as we also would in a standard junit test case.  Because of the use of the ServiceReference we can now just use the service via our local private reference to it.

 

We now need to update the manifest.  As usual we need to add the dependencies to the manifest as shown in figure 4.

 

Figure 4 Adding the Dependencies to the Junit Test

 

A significant difference with a Junit test is there is no Activator.  As a result, we don’t have to add the Activator to the manifest.  However, we do have to add a ‘Test-Suite’ line to the manifest manually.  This is shown in figure 5.

 

Figure 5 Adding the Test-Suite definition

 

At this point we can save the manifest and export both projects as plugins.  Then copy them to the target.  In this example we will place com.esf.example.testing*.jar into the /opt/jvm/esf/dropins/ directory and the com.esf.example.testing.junit*.jar into the /opt/jvm/esf/junit_bundlefiles/ directory.  This is simply a best practice so the test code does not get mixed in with the actual product code.  At a later point before deploying the unit to the field we can simply delete everything in the /opt/jvm/esf/junit_bundlefiles/ directory rather than searching for all of the test bundles.

 

Now we can start ESF.  This is what the output should look like:

 

root@localhost:/opt/jvm/esf> ./start_equinox.sh

 

osgi> [INFO] Junit Extender starting ...

[INFO] Loading com.esf.example.testing.junit.JunitExample

 

Note that the com.esf.example.testing.junit.JunitExample was found and loaded by Junit4OSGi.  Now we need to run our tests.  This is the usage for the junit commands at the ESF console.

 

junit <bundleid> | junit all

 

We can either specify a single junit test bundle or do all of them.  In this case we’ll explicitly state our bundle even though it is the only one.  We need to find the bundle ID from ‘ss’.  This a snippet of the output.

 

116     ACTIVE      org.apache.commons.io_1.4.0

117     ACTIVE      org.apache.commons.net_2.0.0

118     ACTIVE      org.apache.oro_2.0.8

119     ACTIVE      com.esf.example.testing_1.0.0.201007291307

120     ACTIVE      com.esf.example.testing.junit_1.0.0.201007291307

 

osgi>

 

So, our junit bundle is loaded as bundle 120.  We can now run our junit command (junit 120).  This results in the following output.

 

osgi> junit 120

Executing [com.esf.example.testing.junit.JunitExample]

[DEBUG] 2010-07-29 20:51:20.968 - com.esf.example.testing.TestingExample: adding - (5 + 5 which equals 10

[DEBUG] 2010-07-29 20:51:20.969 - com.esf.example.testing.TestingExample: adding - (-5 + 5 which equals 0

[DEBUG] 2010-07-29 20:51:20.969 - com.esf.example.testing.TestingExample: adding - (0 + 10 which equals 10

[DEBUG] 2010-07-29 20:51:20.969 - com.esf.example.testing.TestingExample: adding - (1 + 2 which equals 3

[DEBUG] 2010-07-29 20:51:20.970 - com.esf.example.testing.TestingExample: adding - (20000 + -10000 which equals 10000

[DEBUG] 2010-07-29 20:51:20.971 - com.esf.example.testing.TestingExample: subtracting - (5 - 5 which equals 0

[DEBUG] 2010-07-29 20:51:20.973 - com.esf.example.testing.TestingExample: multiplying - (5 * 5 which equals 0

[DEBUG] 2010-07-29 20:51:20.974 - com.esf.example.testing.TestingExample: multiplying - (-5 * 5 which equals -10

[DEBUG] 2010-07-29 20:51:20.974 - com.esf.example.testing.TestingExample: multiplying - (0 * 10 which equals -10

[DEBUG] 2010-07-29 20:51:20.975 - com.esf.example.testing.TestingExample: multiplying - (1 * 2 which equals -1

[DEBUG] 2010-07-29 20:51:20.975 - com.esf.example.testing.TestingExample: multiplying - (20000 * -10000 which equals 30000

[DEBUG] 2010-07-29 20:51:20.976 - com.esf.example.testing.TestingExample: dividing - (5 / 5 which equals 0

[DEBUG] 2010-07-29 20:51:20.977 - com.esf.example.testing.TestingExample: dividing - (-5 / 5 which equals -10

[DEBUG] 2010-07-29 20:51:20.977 - com.esf.example.testing.TestingExample: dividing - (0 / 10 which equals -10

[DEBUG] 2010-07-29 20:51:20.977 - com.esf.example.testing.TestingExample: dividing - (1 / 2 which equals -1

[DEBUG] 2010-07-29 20:51:20.978 - com.esf.example.testing.TestingExample: dividing - (20000 / -10000 which equals 30000

 

Time: 0.013

There was 1 failure:

1) testSubtraction(com.esf.example.testing.junit.JunitExample)junit.framework.AssertionFailedError: expected:<0> but was:<10>

        at com.esf.example.testing.junit.JunitExample.testSubtraction(JunitExample.java:37)

        at java.lang.reflect.AccessibleObject.invokeV(AccessibleObject.java:195)

        at org.apache.felix.ipojo.junit4osgi.OSGiTestCase.runBare(OSGiTestCase.java:83)

        at org.apache.felix.ipojo.junit4osgi.OSGiTestSuite.runTest(OSGiTestSuite.java:120)

        at org.apache.felix.ipojo.junit4osgi.impl.JunitExtender.__doRun(JunitExtender.java:167)

        at org.apache.felix.ipojo.junit4osgi.impl.JunitExtender.doRun(JunitExtender.java)

        at org.apache.felix.ipojo.junit4osgi.impl.JunitExtender.__run(JunitExtender.java:303)

        at org.apache.felix.ipojo.junit4osgi.impl.JunitExtender.run(JunitExtender.java)

        at org.apache.felix.ipojo.junit4osgi.equinox.JunitEquinox.___junit(JunitEquinox.java:123)

        at org.apache.felix.ipojo.junit4osgi.equinox.JunitEquinox._junit(JunitEquinox.java)

        at java.lang.reflect.AccessibleObject.invokeV(AccessibleObject.java:195)

        at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.execute(FrameworkCommandInterpreter.java:150)

        at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(FrameworkConsole.java:302)

        at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(FrameworkConsole.java:287)

        at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(FrameworkConsole.java:223)

        at java.lang.Thread.run(Thread.java:826)

 

FAILURES!!!

Tests run: 4,  Failures: 1,  Errors: 0

 

junit.framework.AssertionFailedError: expected:<0> but was:<10>

        at junit.framework.Assert.fail(Assert.java:47)

        at junit.framework.Assert.failNotEquals(Assert.java:280)

        at junit.framework.Assert.assertEquals(Assert.java:64)

        at junit.framework.Assert.assertEquals(Assert.java:198)

        at junit.framework.Assert.assertEquals(Assert.java:204)

        at com.esf.example.testing.junit.JunitExample.testSubtraction(JunitExample.java:37)

        at java.lang.reflect.AccessibleObject.invokeV(AccessibleObject.java:195)

        at java.lang.reflect.Method.invoke(Method.java:242)

        at junit.framework.TestCase.runTest(TestCase.java:164)

        at org.apache.felix.ipojo.junit4osgi.OSGiTestCase.runBare(OSGiTestCase.java:83)

        at junit.framework.TestResult$1.protect(TestResult.java:106)

        at junit.framework.TestResult.runProtected(TestResult.java:124)

        at junit.framework.TestResult.run(TestResult.java:109)

        at junit.framework.TestCase.run(TestCase.java:120)

        at org.apache.felix.ipojo.junit4osgi.OSGiTestSuite.runTest(OSGiTestSuite.java:120)

        at junit.framework.TestSuite.run(TestSuite.java:225)

        at org.apache.felix.ipojo.junit4osgi.impl.JunitExtender.__doRun(JunitExtender.java:167)

        at org.apache.felix.ipojo.junit4osgi.impl.JunitExtender.doRun(JunitExtender.java)

        at org.apache.felix.ipojo.junit4osgi.impl.JunitExtender.__run(JunitExtender.java:303)

        at org.apache.felix.ipojo.junit4osgi.impl.JunitExtender.run(JunitExtender.java)

        at org.apache.felix.ipojo.junit4osgi.equinox.JunitEquinox.___junit(JunitEquinox.java:123)

        at org.apache.felix.ipojo.junit4osgi.equinox.JunitEquinox._junit(JunitEquinox.java)

        at java.lang.reflect.AccessibleObject.invokeV(AccessibleObject.java:195)

        at java.lang.reflect.Method.invoke(Method.java:242)

        at org.eclipse.osgi.framework.internal.core.FrameworkCommandInterpreter.execute(FrameworkCommandInterpreter.java:150)

        at org.eclipse.osgi.framework.internal.core.FrameworkConsole.docommand(FrameworkConsole.java:302)

        at org.eclipse.osgi.framework.internal.core.FrameworkConsole.console(FrameworkConsole.java:287)

        at org.eclipse.osgi.framework.internal.core.FrameworkConsole.run(FrameworkConsole.java:223)

        at java.lang.Thread.run(Thread.java:826)

 

 

osgi>

 

Not exactly right.  We can see there was a failure on line 37 of our testSubtraction method.  We know 5 minus 5 is definitely 0 – so it must be a problem with the implementation class of the ITestingExampleService.  Sure enough, there is an error here:

 

      public int subtract(int x, int y) {

            esfLoggerService.logDebug(LABEL + "subtracting - (" + x + " - " + y + " which equals " + (x-y));

            return x+y;

      }

 

That should read:

 

      public int subtract(int x, int y) {

            esfLoggerService.logDebug(LABEL + "subtracting - (" + x + " - " + y + " which equals " + (x-y));

            return x-y;

      }

 

With the changes made and the new code deployed.  This is the test output.

 

osgi> junit 120

Executing [com.esf.example.testing.junit.JunitExample]

[DEBUG] 2010-07-29 20:54:46.845 - com.esf.example.testing.TestingExample: adding - (5 + 5 which equals 10

[DEBUG] 2010-07-29 20:54:46.845 - com.esf.example.testing.TestingExample: adding - (-5 + 5 which equals 0

[DEBUG] 2010-07-29 20:54:46.846 - com.esf.example.testing.TestingExample: adding - (0 + 10 which equals 10

[DEBUG] 2010-07-29 20:54:46.846 - com.esf.example.testing.TestingExample: adding - (1 + 2 which equals 3

[DEBUG] 2010-07-29 20:54:46.846 - com.esf.example.testing.TestingExample: adding - (20000 + -10000 which equals 10000

[DEBUG] 2010-07-29 20:54:46.847 - com.esf.example.testing.TestingExample: subtracting - (5 - 5 which equals 0

[DEBUG] 2010-07-29 20:54:46.847 - com.esf.example.testing.TestingExample: subtracting - (-5 - 5 which equals -10

[DEBUG] 2010-07-29 20:54:46.847 - com.esf.example.testing.TestingExample: subtracting - (0 - 10 which equals -10

[DEBUG] 2010-07-29 20:54:46.848 - com.esf.example.testing.TestingExample: subtracting - (1 - 2 which equals -1

[DEBUG] 2010-07-29 20:54:46.848 - com.esf.example.testing.TestingExample: subtracting - (20000 - -10000 which equals 30000

[DEBUG] 2010-07-29 20:54:46.848 - com.esf.example.testing.TestingExample: multiplying - (5 * 5 which equals 0

[DEBUG] 2010-07-29 20:54:46.849 - com.esf.example.testing.TestingExample: multiplying - (-5 * 5 which equals -10

[DEBUG] 2010-07-29 20:54:46.849 - com.esf.example.testing.TestingExample: multiplying - (0 * 10 which equals -10

[DEBUG] 2010-07-29 20:54:46.849 - com.esf.example.testing.TestingExample: multiplying - (1 * 2 which equals -1

[DEBUG] 2010-07-29 20:54:46.850 - com.esf.example.testing.TestingExample: multiplying - (20000 * -10000 which equals 30000

[DEBUG] 2010-07-29 20:54:46.850 - com.esf.example.testing.TestingExample: dividing - (5 / 5 which equals 0

[DEBUG] 2010-07-29 20:54:46.850 - com.esf.example.testing.TestingExample: dividing - (-5 / 5 which equals -10

[DEBUG] 2010-07-29 20:54:46.851 - com.esf.example.testing.TestingExample: dividing - (0 / 10 which equals -10

[DEBUG] 2010-07-29 20:54:46.851 - com.esf.example.testing.TestingExample: dividing - (1 / 2 which equals -1

[DEBUG] 2010-07-29 20:54:46.851 - com.esf.example.testing.TestingExample: dividing - (20000 / -10000 which equals 30000

 

Time: 0.013

 

OK (4 tests)

 

---Junit4OSGi Commands---

        junit <bundleid> | junit all

 

 

osgi>

 

The tests all passed without a problem and our bug is fixed.

 

Manual Testing

There are times where unfortunately tests can not be completely automated with junit.  Most can, and when the use of junit is possible it is always preferable.  But, sometimes it makes sense to manually test the software with real hardware I/O or devices.  When this is the case it is possible to use the ESF Manual Testing Harness.  In this case we won’t use actual hardware to test.  Instead we’ll use the example project from above.  To make the example more interesting insert the bug back in that we found with the junit test.

 

Start by creating a project with the following details.

 

 

This is the Activator code.

 

package com.esf.example.testing.manual.bundle;

 

import org.eclipse.soda.sat.core.framework.BaseBundleActivator;

 

import com.esf.example.testing.manual.ManualExample;

import com.esf.example.testing.service.ITestingExampleService;

import com.esf.testing.tcpconsole.service.ITcpConsoleService;

 

public class Activator extends BaseBundleActivator {

     

      private ManualExample manualExample = null;

 

      protected void activate() {

            manualExample = new ManualExample();

            manualExample.bind(getITestingExampleService(), getITcpConsoleService());

      }

     

      protected void deactivate() {

            manualExample.unbind();

            manualExample = null;

      }

     

      private ITestingExampleService getITestingExampleService() {

            return (ITestingExampleService) getImportedService (ITestingExampleService.SERVICE_NAME);

      }

     

      private ITcpConsoleService getITcpConsoleService() {

            return (ITcpConsoleService) getImportedService (ITcpConsoleService.SERVICE_NAME);

      }

     

      protected String[] getImportedServiceNames() {

            return new String[] {

                        ITestingExampleService.SERVICE_NAME,

                        ITcpConsoleService.SERVICE_NAME

            };

      }

}

 

There is nothing new here.  Note the acquisition of the ITcpConsoleService.

 

This is the actual test code (com.esf.example.testing.manual.ManualExample).

 

package com.esf.example.testing.manual;

 

import java.util.ArrayList;

import java.util.StringTokenizer;

 

import com.esf.example.testing.service.ITestingExampleService;

import com.esf.testing.tcpconsole.service.Command;

import com.esf.testing.tcpconsole.service.ITcpConsoleService;

 

public class ManualExample {

 

      private static ITestingExampleService testingExampleService;

      private ITcpConsoleService tcpConsoleService;

      private ArrayList commands;

 

      public void bind(ITestingExampleService testingExampleService, ITcpConsoleService tcpConsoleService) {

            ManualExample.testingExampleService = testingExampleService;

            this.tcpConsoleService = tcpConsoleService;

            commands = new ArrayList();

            commands.add(new Command(this, "add", getAddUsage()));

            commands.add(new Command(this, "sub", getSubUsage()));

            commands.add(new Command(this, "mult", getMultUsage()));

            commands.add(new Command(this, "div", getDivUsage()));

           

            try {

                  tcpConsoleService.registerCommands(commands);

            } catch(Exception e) {

                  e.printStackTrace();

            }

      }

 

      public void unbind() {

            try {

                  tcpConsoleService.unregisterCommands(commands);

            } catch(Exception e) {

                  e.printStackTrace();

            }

           

            commands = null;

            tcpConsoleService = null;

            ManualExample.testingExampleService = null;

      }

 

      public String addAction(String command) throws Exception {

            try {

                  StringTokenizer st = new StringTokenizer(command);

 

                  st.nextToken();   //skip 'add'

                  int x = Integer.parseInt(st.nextToken());

                  int y = Integer.parseInt(st.nextToken());

                 

                  if(testingExampleService.add(x, y) == (x+y)) {

                        return new String(x + "+" + y + " is properly equal to " + (x+y) + "\n\n");

                  } else {

                        return new String("ERROR: " + x + "+" + y + " is NOT properly equal to " + (x+y) + "  It is " + testingExampleService.add(x, y) + "\n\n");

                  }

            } catch(Exception e) {

                  e.printStackTrace();

                  return getAddUsage();

            }

      }

     

      public String subAction(String command) throws Exception {

            try {

                  StringTokenizer st = new StringTokenizer(command);

 

                  st.nextToken();   //skip 'sub'

                  int x = Integer.parseInt(st.nextToken());

                  int y = Integer.parseInt(st.nextToken());

                 

                  if(testingExampleService.subtract(x, y) == (x-y)) {

                        return new String(x + "-" + y + " is properly equal to " + (x-y) + "\n\n");

                  } else {

                        return new String("ERROR: " + x + "-" + y + " is NOT properly equal to " + (x-y) + "  It is " + testingExampleService.subtract(x, y) + "\n\n");

                  }

            } catch(Exception e) {

                  e.printStackTrace();

                  return getSubUsage();

            }

      }

     

      public String multAction(String command) throws Exception {

            try {

                  StringTokenizer st = new StringTokenizer(command);

 

                  st.nextToken();   //skip 'mult'

                  int x = Integer.parseInt(st.nextToken());

                  int y = Integer.parseInt(st.nextToken());

                 

                  if(testingExampleService.multiply(x, y) == (x*y)) {

                        return new String(x + "*" + y + " is properly equal to " + (x*y) + "\n\n");

                  } else {

                        return new String("ERROR: " + x + "*" + y + " is NOT properly equal to " + (x*y) + "  It is " + testingExampleService.multiply(x, y) + "\n\n");

                  }

            } catch(Exception e) {

                  e.printStackTrace();

                  return getMultUsage();

            }

      }

     

      public String divAction(String command) throws Exception {

            try {

                  StringTokenizer st = new StringTokenizer(command);

 

                  st.nextToken();   //skip 'div'

                  int x = Integer.parseInt(st.nextToken());

                  int y = Integer.parseInt(st.nextToken());

                 

                  if(testingExampleService.divide(x, y) == (x/y)) {

                        return new String(x + "/" + y + " is properly equal to " + (x/y) + "\n\n");

                  } else {

                        return new String("ERROR: " + x + "/" + y + " is NOT properly equal to " + (x/y) + "  It is " + testingExampleService.divide(x, y) + "\n\n");

                  }

            } catch(Exception e) {

                  e.printStackTrace();

                  return getDivUsage();

            }

      }

     

      public String getAddUsage() {

            return "add [x] [y]\n";

      }

     

      public String getSubUsage() {

            return "sub [x] [y]\n";

      }

     

      public String getMultUsage() {

            return "mult [x] [y]\n";

      }

     

      public String getDivUsage() {

            return "div [x] [y]\n";

      }

}

 

This is a bit more complex.  We’ll cover this in the following groupings.

 

bind()/unbind()

These are the standard mechanisms for getting our required service handles into our bundle.  Of interest in this bind is the registration of some ‘commands’.  The ITcpConsoleService is a service that provides a console on a specific TCP port.  One can connect via telnet to issue commands and see the responses.  Various manual test bundles such as this one can register commands to add them to the consoles capabilities.  These registered commands are what the TcpConsoleService supports at any given point in time.  Note also this is completely separate from the standard ESF console so the test harness doesn’t interfere in any way with the normal operation of ESF.

 

It is also important to note that the testingServiceExample instance is static.  This is required in this case because of how the TcpConsoleService is implemented and how it uses reflection with each of the manual command providers in the framework.  If this is not static you will get null pointer exceptions from the TcpConsoleService when it tries to issue the commands.

 

*Action() methods

The *Action methods correlate one to one to the commands.  Each Action method must be named [command]Action.  They must also take a String as an argument and return a String (i.e. command/response).  If these are not named in this way the commands will not work.

 

get*Usage() methods

These are helper methods to get the usage for individual commands.  The ITcpConsoleService uses these as needed when a user of the TCP console requests usage information or when they incorrectly use the specific command.

 

Before deploying your new bundle make sure you specify the Activator and add the required dependencies to the manifest.  Finally, deploy the bundle to the target in the /opt/jvm/esf/junit_bundlefiles/ directory.  Once there start ESF again.  You should see your bundle now running via the output of ss.

 

119     ACTIVE      org.apache.commons.io_1.4.0

120     ACTIVE      org.apache.commons.net_2.0.0

121     ACTIVE      org.apache.oro_2.0.8

122     ACTIVE      com.esf.example.testing_1.0.0.201007291354

123     ACTIVE      com.esf.example.testing.manual_1.0.0.201007291450

124     ACTIVE      com.esf.example.testing.junit_1.0.0.201007291307

 

osgi>

 

At this point you can connect to port 10000 using a telnet client such as putty.  You should see something similar to what is shown in figure 6 (i.e. the etf console prompt).

 

Figure 6 The ETF Console Prompt

 

This is the output of my manual test session:

 

etf> help

Invalid Command!

Valid commands are:

 

Command: add

Usage: add [x] [y]

 

Command: sub

Usage: sub [x] [y]

 

Command: mult

Usage: mult [x] [y]

 

Command: div

Usage: div [x] [y]

 

etf> add 10 10

10+10 is properly equal to 20

 

etf> sub 20 10

ERROR: 20-10 is NOT properly equal to 10  It is 30

 

etf> mult 10 10

10*10 is properly equal to 100

 

etf> div 100 10

100/10 is properly equal to 10

 

etf>

 

Note that it errors on the subtract.  This is because of our bug.  We can go back and fix that now and redeploy.  This is the now resolved output.

 

etf> add 10 10

10+10 is properly equal to 20

 

etf> sub 99 9

99-9 is properly equal to 90

 

etf> mult 12 12

12*12 is properly equal to 144

 

etf> div 100 5

100/5 is properly equal to 20

 

etf>

 

Manual testing is convenient for event driven situations where there is not an emulator or some way to automate the input.  For example in testing ESF there is an API for detecting whether or not an Ethernet link is detected.  A junit test is not ideal here because junit doesn’t know whether or not a link is actually present.  This is where the manual tests can come in handy.

 

You can download all of the code for this example here.  You can follow this procedure to install it.

 

<<Previous     Quickstart     Next>>

 

Copyright © 2010 Eurotech Inc.  All rights reserved.