Testing Example

PART 3. ESF CODE EXAMPLES
Testing

 

Example

·            Overview

·            Prerequisites

·            Junit Testing

·            Manual Testing

Example

 

Overview

This how-to shows some mechanisms for testing and running test code.

 

In this example, you will learn how to

·            Use Junit within ESF

·            Use the ESF manual test harness

·            Use the ESF console tested

           

Prerequisites

·            Installing the Eclipse IDE

·            Integrating ESF Tooling and Projects into Eclipse

or

·            Installing ESF Tooling into Wind River Workbench

and

·            Using Working Sets

·            Hello World Using the ESF Log Service

 

Junit Testing

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

 

·            Project (bundle) Name

1.    com.esf.example.testing

·            Imported Services (to be added to the Automated Management of Dependencies list in the Eclipse Manifest Editor)

1.    org.eclipse.osgi

2.    org.eclipse.soda.sat.core

3.    com.esf.core.logger.service

·            Service Interface (with Package Name)

1.    com.esf.example.testing.service.ITestingExampleService

·            Activator Class Name (with Package Name)

1.    com.esf.example.testing.bundle.Activator

·            Implementation Class Name (with Package Name)

1.    com.esf.example.testing.TestingExample

 

The following 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);

}

 

 

The following 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 Activator is standard and simple.  Note we are exporting the ITestingExampleService to OSGi.  The following is the main implementation class.

 

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;

      }

}

 

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

 

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.  See the screen captures for Steps 1, 2, and 3 below.

 

Step 1: Exporting the Service API Package:

 

 

 

Step 2: Adding the Activator to the Manifest:

 

 

 

Step 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.  The following is the basic information on this bundle.

 

·            Project (bundle) Name

1.    com.esf.example.testing.junit

·            Imported Services (to be added to the Automated Management of Dependencies list in the Eclipse Manifest Editor)

1.    org.eclipse.osgi

2.    org.apache.felix.ipojo.junit4osgi

3.    com.esf.example.testing

·            Junit Test Class Name (with Package Name)

1.    com.esf.example.testing.junit.JunitExample

 

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.  They are used like standard Junit test setUp() and tearDown() methods.  But, 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 just use the service via our local private reference to it.

 

Next, update the manifest.  As usual, you need to add the dependencies to the manifest.

 

 

 

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

 

 

 

At this point, you can save the manifest, export both projects as plugins, and then copy them to the target.  In this example, you 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, you can simply delete everything in the /opt/jvm/esf/junit_bundlefiles/ directory rather than searching for the entire test bundles.

 

 

The next step is to start ESF.  The following 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 run our tests.  The following 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’.  The following is 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>

 

Our junit bundle is loaded as bundle 120.  Run our junit command (junit 120).  This command 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>

 

The results are not exactly right.  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 in the following code.

 

      public int subtract(int x, int y) {

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

            return x+y;

      }

 

The correction is

 

      public int subtract(int x, int y) {

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

            return x-y;

      }

 

With the correction made and the new code deployed, the test output is as follows.

 

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>

 

All tests passed without a problem, and our bug is fixed.

 

Manual Testing

Unfortunately, there are times when tests cannot 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.  At these times, 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 the previous section.  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.

 

·            Project (bundle) Name

1.    com.esf.example.testing.manual

·            Imported Services (to be added to the Automated Management of Dependencies list in the Eclipse Manifest Editor)

1.    org.eclipse.osgi

2.    org.eclipse.soda.sat.core

3.    com.esf.testing.tcpconsole.service

4.    com.esf.example.testing

·            Activator Class Name (with Package Name)

1.    com.esf.example.testing.manual.bundle.Activator

·            Implementation Class Name (with Package Name)

1.    com.esf.example.testing.manual.ManualExample

 

The following 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

            };

      }

}

 

This example is very similar to previous examples.  Notice the acquisition of the ITcpConsoleService.

 

The following 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 example is a bit more complex.  We’ll cover this in the following groupings:

bind()/unbind()

*Action() methods

get*Usage() methods

 

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.  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.  It 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

The get*Usage methods are helper methods to get the usage for individual commands.  The ITcpConsoleService uses these methods 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 the etf console prompt similar to what is shown in figure 6.

 

 

The following output is from a 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>

 

Notice that it errors on the subtract because of our bug.  We can fix that error now and redeploy.  The following is the 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.  In this case, 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.