コード例 #1
0
  /**
   * Auxiliary method obtain the JSON fields and their values
   *
   * @param fmJson
   * @param sv
   */
  public static void jsonConverter(String fmJson, IStatsService sv) {

    MappingJsonFactory f = new MappingJsonFactory();
    JsonParser jp;
    try {
      try {
        jp = f.createJsonParser(fmJson);
      } catch (JsonParseException e) {
        throw new IOException(e);
      }

      jp.nextToken();
      if (jp.getCurrentToken() != JsonToken.START_OBJECT) {
        throw new IOException("Expected START_OBJECT");
      }

      while (jp.nextToken() != JsonToken.END_OBJECT) {
        if (jp.getCurrentToken() != JsonToken.FIELD_NAME) {
          throw new IOException("Expected FIELD_NAME");
        }

        String n = jp.getCurrentName();
        jp.nextToken();
        if (jp.getText().equals("")) {
          continue;
        }

        // This assumes user having dpid info for involved switches
        else if (n.equalsIgnoreCase("srcDpid")) {
          try {
            srcId = DatapathId.of(jp.getText());
          } catch (NumberFormatException e) {
            log.error("Unable to parse switch DPID: {}", jp.getText());
            // TODO should return some error message via HTTP message
          }
        } else if (n.equalsIgnoreCase("dstDpid")) {
          try {
            dstId = DatapathId.of(jp.getText());
          } catch (NumberFormatException e) {
            log.error("Unable to parse switch DPID: {}", jp.getText());
            // TODO should return some error message via HTTP message
          }
        } else if (n.equalsIgnoreCase("srcIp")) {
          try {
            srcIp = IPv4Address.of(jp.getText());
          } catch (NumberFormatException e) {
            log.error("Unable to parse IP srcIp: {}", jp.getText());
            // TODO should return some error message via HTTP message
          }
        } else if (n.equalsIgnoreCase("dstIp")) {
          try {
            dstIp = IPv4Address.of(jp.getText());
          } catch (NumberFormatException e) {
            log.error("Unable to parse IP dstIp: {}", jp.getText());
            // TODO should return some error message via HTTP message
          }
        } else if (n.equalsIgnoreCase("loss")) {
          try {
            loss = Integer.parseInt(jp.getText());
          } catch (NumberFormatException e) {
            log.error("Unable to parse loss: {}", jp.getText());
            // TODO should return some error message via HTTP message
          }
        }
      }

    } catch (IOException e) {
      log.error("Unable to parse JSON string: {}", e);
    }
  }
コード例 #2
0
public class ControllerTest extends FloodlightTestCase {

  private Controller controller;
  private MockThreadPoolService tp;
  private MockSyncService syncService;
  private IPacket testPacket;
  private OFPacketIn pi;

  // FIXME:LOJI: For now just work with OF 1.0
  private final OFFactory factory = OFFactories.getFactory(OFVersion.OF_10);
  private static DatapathId DATAPATH_ID_0 = DatapathId.of(0);

  @Override
  @Before
  public void setUp() throws Exception {
    doSetUp(HARole.ACTIVE);
  }

  public void doSetUp(HARole role) throws Exception {
    super.setUp();
    FloodlightModuleContext fmc = new FloodlightModuleContext();
    FloodlightProvider cm = new FloodlightProvider();

    fmc.addConfigParam(cm, "role", role.toString());
    controller = (Controller) cm.getServiceImpls().get(IFloodlightProviderService.class);
    fmc.addService(IFloodlightProviderService.class, controller);

    MemoryStorageSource memstorage = new MemoryStorageSource();
    fmc.addService(IStorageSourceService.class, memstorage);

    RestApiServer restApi = new RestApiServer();
    fmc.addService(IRestApiService.class, restApi);

    ThreadPool threadPool = new ThreadPool();
    fmc.addService(IThreadPoolService.class, threadPool);

    MockSwitchManager switchService = new MockSwitchManager();
    fmc.addService(IOFSwitchService.class, switchService);

    PktInProcessingTime ppt = new PktInProcessingTime();
    fmc.addService(IPktInProcessingTimeService.class, ppt);

    // TODO: should mock IDebugCounterService and make sure
    // the expected counters are updated.
    DebugCounterServiceImpl debugCounterService = new DebugCounterServiceImpl();
    fmc.addService(IDebugCounterService.class, debugCounterService);

    DebugEventService debugEventService = new DebugEventService();
    fmc.addService(IDebugEventService.class, debugEventService);

    IShutdownService shutdownService = createMock(IShutdownService.class);
    shutdownService.registerShutdownListener(anyObject(IShutdownListener.class));
    expectLastCall().anyTimes();
    replay(shutdownService);
    fmc.addService(IShutdownService.class, shutdownService);
    verify(shutdownService);

    tp = new MockThreadPoolService();
    fmc.addService(IThreadPoolService.class, tp);

    syncService = new MockSyncService();
    fmc.addService(ISyncService.class, syncService);

    ppt.init(fmc);
    restApi.init(fmc);
    threadPool.init(fmc);
    memstorage.init(fmc);
    tp.init(fmc);
    debugCounterService.init(fmc);
    debugEventService.init(fmc);
    syncService.init(fmc);
    cm.init(fmc);

    ppt.startUp(fmc);
    restApi.startUp(fmc);
    threadPool.startUp(fmc);
    memstorage.startUp(fmc);
    tp.startUp(fmc);
    debugCounterService.startUp(fmc);
    debugEventService.startUp(fmc);
    syncService.startUp(fmc);
    cm.startUp(fmc);

    testPacket =
        new Ethernet()
            .setSourceMACAddress("00:44:33:22:11:00")
            .setDestinationMACAddress("00:11:22:33:44:55")
            .setEtherType(EthType.ARP)
            .setPayload(
                new ARP()
                    .setHardwareType(ARP.HW_TYPE_ETHERNET)
                    .setProtocolType(ARP.PROTO_TYPE_IP)
                    .setHardwareAddressLength((byte) 6)
                    .setProtocolAddressLength((byte) 4)
                    .setOpCode(ARP.OP_REPLY)
                    .setSenderHardwareAddress(Ethernet.toMACAddress("00:44:33:22:11:00"))
                    .setSenderProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.1"))
                    .setTargetHardwareAddress(Ethernet.toMACAddress("00:11:22:33:44:55"))
                    .setTargetProtocolAddress(IPv4.toIPv4AddressBytes("192.168.1.2")));
    byte[] testPacketSerialized = testPacket.serialize();

    // The specific factory can be obtained from the switch, but we don't have one
    pi =
        (OFPacketIn)
            factory
                .buildPacketIn()
                .setBufferId(OFBufferId.NO_BUFFER)
                .setInPort(OFPort.of(1))
                .setData(testPacketSerialized)
                .setReason(OFPacketInReason.NO_MATCH)
                .setTotalLen(testPacketSerialized.length)
                .build();
  }

  @After
  public void tearDown() {
    tp.getScheduledExecutor().shutdownNow();
    // Make sure thare are not left over updates in the queue
    assertTrue(
        "Updates left in controller update queue", controller.isUpdateQueueEmptyForTesting());
  }

  public Controller getController() {
    return controller;
  }

  private static SwitchDescription createSwitchDescription() {
    return new SwitchDescription();
  }

  private OFFeaturesReply createOFFeaturesReply(DatapathId datapathId) {
    OFFeaturesReply fr =
        factory
            .buildFeaturesReply()
            .setXid(0)
            .setDatapathId(datapathId)
            .setPorts(ImmutableList.<OFPortDesc>of())
            .build();
    return fr;
  }

  /**
   * Set the mock expectations for sw when sw is passed to addSwitch The same expectations can be
   * used when a new SwitchSyncRepresentation is created from the given mocked switch
   */
  protected void setupSwitchForAddSwitch(
      IOFSwitch sw,
      DatapathId datapathId,
      SwitchDescription description,
      OFFeaturesReply featuresReply) {
    String dpidString = datapathId.toString();
    if (description == null) {
      description = createSwitchDescription();
    }
    if (featuresReply == null) {
      featuresReply = createOFFeaturesReply(datapathId);
    }
    List<OFPortDesc> ports = featuresReply.getPorts();

    expect(sw.getOFFactory()).andReturn(OFFactories.getFactory(OFVersion.OF_10)).anyTimes();
    expect(sw.getId()).andReturn(datapathId).anyTimes();
    expect(sw.getId().toString()).andReturn(dpidString).anyTimes();
    expect(sw.getSwitchDescription()).andReturn(description).atLeastOnce();
    expect(sw.getBuffers()).andReturn(featuresReply.getNBuffers()).atLeastOnce();
    expect(sw.getTables()).andReturn(featuresReply.getNTables()).atLeastOnce();
    expect(sw.getCapabilities()).andReturn(featuresReply.getCapabilities()).atLeastOnce();
    expect(sw.getActions()).andReturn(featuresReply.getActions()).atLeastOnce();
    expect(sw.getPorts()).andReturn(ports).atLeastOnce();
    expect(sw.attributeEquals(IOFSwitch.SWITCH_SUPPORTS_NX_ROLE, true)).andReturn(false).anyTimes();
    expect(sw.getInetAddress()).andReturn(null).anyTimes();
  }

  @SuppressWarnings("unchecked")
  private <T> void setupListenerOrdering(IListener<T> listener) {
    listener.isCallbackOrderingPostreq((T) anyObject(), anyObject(String.class));
    expectLastCall().andReturn(false).anyTimes();

    listener.isCallbackOrderingPrereq((T) anyObject(), anyObject(String.class));
    expectLastCall().andReturn(false).anyTimes();
  }

  @Test
  public void testHandleMessagesNoListeners() throws Exception {
    IOFSwitch sw = createMock(IOFSwitch.class);
    expect(sw.getId()).andReturn(DatapathId.NONE).anyTimes();
    replay(sw);
    controller.handleMessage(sw, pi, null);
    verify(sw);
  }

  /**
   * Test message dispatching to OFMessageListeners. Test ordering of listeners for different types
   * (we do this implicitly by using STOP and CONTINUE and making sure the processing stops at the
   * right place) Verify that a listener that throws an exception halts further execution, and
   * verify that the Commands STOP and CONTINUE are honored.
   *
   * @throws Exception
   */
  @Test
  public void testHandleMessages() throws Exception {
    controller.removeOFMessageListeners(OFType.PACKET_IN);

    IOFSwitch sw = createMock(IOFSwitch.class);
    expect(sw.getId()).andReturn(DatapathId.NONE).anyTimes();

    // Setup listener orderings
    IOFMessageListener test1 = createMock(IOFMessageListener.class);
    expect(test1.getName()).andReturn("test1").anyTimes();
    setupListenerOrdering(test1);

    IOFMessageListener test2 = createMock(IOFMessageListener.class);
    expect(test2.getName()).andReturn("test2").anyTimes();
    // using a postreq and a prereq ordering here
    expect(test2.isCallbackOrderingPrereq(OFType.PACKET_IN, "test1")).andReturn(true).atLeastOnce();
    expect(test2.isCallbackOrderingPostreq(OFType.FLOW_MOD, "test1")).andReturn(true).atLeastOnce();
    setupListenerOrdering(test2);

    IOFMessageListener test3 = createMock(IOFMessageListener.class);
    expect(test3.getName()).andReturn("test3").anyTimes();
    expect(test3.isCallbackOrderingPrereq((OFType) anyObject(), eq("test1")))
        .andReturn(true)
        .atLeastOnce();
    expect(test3.isCallbackOrderingPrereq((OFType) anyObject(), eq("test2")))
        .andReturn(true)
        .atLeastOnce();
    setupListenerOrdering(test3);

    // Ordering: PacketIn: test1 -> test2 -> test3
    //           FlowMod:  test2 -> test1
    replay(test1, test2, test3);
    controller.addOFMessageListener(OFType.PACKET_IN, test1);
    controller.addOFMessageListener(OFType.PACKET_IN, test3);
    controller.addOFMessageListener(OFType.PACKET_IN, test2);
    controller.addOFMessageListener(OFType.FLOW_MOD, test1);
    controller.addOFMessageListener(OFType.FLOW_MOD, test2);
    verify(test1);
    verify(test2);
    verify(test3);

    replay(sw);

    // ------------------
    // Test PacketIn handling: all listeners return CONTINUE
    reset(test1, test2, test3);
    expect(test1.receive(eq(sw), eq(pi), isA(FloodlightContext.class))).andReturn(Command.CONTINUE);
    expect(test2.receive(eq(sw), eq(pi), isA(FloodlightContext.class))).andReturn(Command.CONTINUE);
    expect(test3.receive(eq(sw), eq(pi), isA(FloodlightContext.class))).andReturn(Command.CONTINUE);
    replay(test1, test2, test3);
    controller.handleMessage(sw, pi, null);
    verify(test1);
    verify(test2);
    verify(test3);

    // ------------------
    // Test PacketIn handling: with a thrown exception.
    reset(test1, test2, test3);
    expect(test1.receive(eq(sw), eq(pi), isA(FloodlightContext.class))).andReturn(Command.CONTINUE);
    expect(test2.receive(eq(sw), eq(pi), isA(FloodlightContext.class)))
        .andThrow(
            new RuntimeException("This is NOT an error! We " + "are testing exception catching."));
    // expect no calls to test3.receive() since test2.receive throws
    // an exception
    replay(test1, test2, test3);
    try {
      controller.handleMessage(sw, pi, null);
      fail("Expected exception was not thrown!");
    } catch (RuntimeException e) {
      assertTrue(
          "The caught exception was not the expected one",
          e.getMessage().startsWith("This is NOT an error!"));
    }
    verify(test1);
    verify(test2);
    verify(test3);

    // ------------------
    // Test PacketIn handling: test1 return Command.STOP
    reset(test1, test2, test3);
    expect(test1.receive(eq(sw), eq(pi), isA(FloodlightContext.class))).andReturn(Command.STOP);
    // expect no calls to test3.receive() and test2.receive since
    // test1.receive returns STOP
    replay(test1, test2, test3);
    controller.handleMessage(sw, pi, null);
    verify(test1);
    verify(test2);
    verify(test3);

    OFFlowMod fm = (OFFlowMod) factory.buildFlowModify().build();

    // ------------------
    // Test FlowMod handling: all listeners return CONTINUE
    reset(test1, test2, test3);
    expect(test1.receive(eq(sw), eq(fm), isA(FloodlightContext.class))).andReturn(Command.CONTINUE);
    expect(test2.receive(eq(sw), eq(fm), isA(FloodlightContext.class))).andReturn(Command.CONTINUE);
    // test3 is not a listener for FlowMod
    replay(test1, test2, test3);
    controller.handleMessage(sw, fm, null);
    verify(test1);
    verify(test2);
    verify(test3);

    // ------------------
    // Test FlowMod handling: test2 (first listener) return STOP
    reset(test1, test2, test3);
    expect(test2.receive(eq(sw), eq(fm), isA(FloodlightContext.class))).andReturn(Command.STOP);
    // test2 will not be called
    // test3 is not a listener for FlowMod
    replay(test1, test2, test3);
    controller.handleMessage(sw, fm, null);
    verify(test1);
    verify(test2);
    verify(test3);

    verify(sw);
  }

  @Test
  public void testHandleMessagesSlave() throws Exception {
    doSetUp(HARole.STANDBY);
    IOFSwitch sw = createMock(IOFSwitch.class);
    expect(sw.getId()).andReturn(DatapathId.NONE).anyTimes();

    IOFMessageListener test1 = createMock(IOFMessageListener.class);
    expect(test1.getName()).andReturn("test1").atLeastOnce();
    expect(test1.isCallbackOrderingPrereq((OFType) anyObject(), (String) anyObject()))
        .andReturn(false)
        .atLeastOnce();
    expect(test1.isCallbackOrderingPostreq((OFType) anyObject(), (String) anyObject()))
        .andReturn(false)
        .atLeastOnce();

    replay(test1, sw);
    controller.addOFMessageListener(OFType.PACKET_IN, test1);
    // message should not be dispatched
    controller.handleMessage(sw, pi, null);
    verify(test1);

    // ---------------------------------
    // transition to Master
    // --------------------------------
    controller.setRole(HARole.ACTIVE, "FooBar");

    // transitioned but HA listeneres not yet notified.
    // message should not be dispatched
    reset(test1);
    replay(test1);
    controller.handleMessage(sw, pi, null);
    verify(test1);

    // notify HA listeners
    controller.processUpdateQueueForTesting();
    // no message should be dispatched
    reset(test1);
    expect(test1.receive(eq(sw), eq(pi), isA(FloodlightContext.class))).andReturn(Command.STOP);
    replay(test1);
    controller.handleMessage(sw, pi, null);
    verify(test1);

    verify(sw);
  }

  @Test
  public void testHandleMessageWithContext() throws Exception {
    IOFSwitch sw = createMock(IOFSwitch.class);
    expect(sw.getId()).andReturn(DatapathId.NONE).anyTimes();

    IOFMessageListener test1 = createMock(IOFMessageListener.class);
    expect(test1.getName()).andReturn("test1").anyTimes();
    expect(test1.isCallbackOrderingPrereq((OFType) anyObject(), (String) anyObject()))
        .andReturn(false)
        .anyTimes();
    expect(test1.isCallbackOrderingPostreq((OFType) anyObject(), (String) anyObject()))
        .andReturn(false)
        .anyTimes();
    FloodlightContext cntx = new FloodlightContext();
    expect(test1.receive(same(sw), same(pi), same(cntx))).andReturn(Command.CONTINUE);

    IOFMessageListener test2 = createMock(IOFMessageListener.class);
    expect(test2.getName()).andReturn("test2").anyTimes();
    expect(test2.isCallbackOrderingPrereq((OFType) anyObject(), (String) anyObject()))
        .andReturn(false)
        .anyTimes();
    expect(test2.isCallbackOrderingPostreq((OFType) anyObject(), (String) anyObject()))
        .andReturn(false)
        .anyTimes();
    // test2 will not receive any message!

    replay(test1, test2, sw);
    controller.addOFMessageListener(OFType.PACKET_IN, test1);
    controller.addOFMessageListener(OFType.ERROR, test2);
    controller.handleMessage(sw, pi, cntx);
    verify(test1, test2, sw);

    Ethernet eth =
        IFloodlightProviderService.bcStore.get(cntx, IFloodlightProviderService.CONTEXT_PI_PAYLOAD);
    assertArrayEquals(testPacket.serialize(), eth.serialize());
  }

  /**
   * Test handleOutgoingMessage and also test listener ordering
   *
   * @throws Exception
   */
  @Test
  public void testHandleOutgoingMessage() throws Exception {
    OFMessage m = factory.buildEchoRequest().build();
    IOFSwitchBackend sw = createMock(IOFSwitchBackend.class);
    expect(sw.getId()).andReturn(DATAPATH_ID_0).anyTimes();

    // Add listeners
    IOFMessageListener test1 = createMock(IOFMessageListener.class);
    expect(test1.getName()).andReturn("test1").anyTimes();
    setupListenerOrdering(test1);

    IOFMessageListener test2 = createMock(IOFMessageListener.class);
    expect(test2.getName()).andReturn("test2").anyTimes();
    test2.isCallbackOrderingPostreq(OFType.ECHO_REQUEST, "test1");
    expectLastCall().andReturn(true).atLeastOnce();
    setupListenerOrdering(test2);

    IOFMessageListener test3 = createMock(IOFMessageListener.class);
    expect(test3.getName()).andReturn("test3").anyTimes();
    test3.isCallbackOrderingPostreq(OFType.ECHO_REQUEST, "test2");
    expectLastCall().andReturn(true).atLeastOnce();
    setupListenerOrdering(test3);

    // expected ordering is test3, test2, test1

    replay(test1, test2, test3);
    controller.addOFMessageListener(OFType.ECHO_REQUEST, test1);
    controller.addOFMessageListener(OFType.ECHO_REQUEST, test3);
    controller.addOFMessageListener(OFType.ECHO_REQUEST, test2);
    verify(test1);
    verify(test2);
    verify(test3);

    // Test inject with null switch and no message. Should not work.
    reset(test1, test2, test3);
    replay(test1, test2, test3, sw);
    try {
      controller.handleOutgoingMessage(null, pi);
      fail("handleOutgoindMessage should have thrown a NPE");
    } catch (NullPointerException e) {
      // expected
    }
    try {
      controller.handleOutgoingMessage(sw, null);
      fail("handleOutgoingMessage should have thrown a NPE");
    } catch (NullPointerException e) {
      // expected
    }
    verify(test1);
    verify(test2);
    verify(test3);
    verify(sw);

    // Test the handleOutgoingMessage
    reset(test1, test2, test3, sw);
    expect(sw.getId()).andReturn(DATAPATH_ID_0).anyTimes();
    expect(test2.receive(same(sw), same(m), isA(FloodlightContext.class))).andReturn(Command.STOP);
    expect(test3.receive(same(sw), same(m), isA(FloodlightContext.class)))
        .andReturn(Command.CONTINUE);
    // test1 will not receive any message!
    replay(test1, test2, test3, sw);
    controller.handleOutgoingMessage(sw, m);
    verify(test1);
    verify(test2);
    verify(test3);
    verify(sw);

    // Test the handleOutgoingMessage with null context
    reset(test1, test2, test3, sw);
    expect(sw.getId()).andReturn(DATAPATH_ID_0).anyTimes();
    expect(test2.receive(same(sw), same(m), isA(FloodlightContext.class))).andReturn(Command.STOP);
    expect(test3.receive(same(sw), same(m), isA(FloodlightContext.class)))
        .andReturn(Command.CONTINUE);
    // test1 will not receive any message!
    replay(test1, test2, test3, sw);
    controller.handleOutgoingMessage(sw, m);
    verify(test1);
    verify(test2);
    verify(test3);
    verify(sw);

    // Test for message without listeners
    reset(test1, test2, test3, sw);
    replay(test1, test2, test3, sw);
    m = factory.buildEchoReply().build();
    controller.handleOutgoingMessage(sw, m);
    verify(test1);
    verify(test2);
    verify(test3);
    verify(sw);
  }

  @Test
  public void testGetRoleInfoDefault() {
    RoleInfo info = controller.getRoleInfo();
    assertEquals(HARole.ACTIVE, info.getRole());
    assertNotNull(info.getRoleChangeDescription());
    assertEquals(HARole.ACTIVE, controller.getRole());
    // FIXME: RoleInfo's date. but the format is kinda broken
  }

  /** Test interaction with OFChannelHandler when the current role is master. */
  @Test
  public void testChannelHandlerMaster() {
    OFSwitchHandshakeHandler h = createMock(OFSwitchHandshakeHandler.class);

    // Reassert the role.
    reset(h);
    h.sendRoleRequestIfNotPending(OFControllerRole.ROLE_MASTER);
    replay(h);
    controller.reassertRole(h, HARole.ACTIVE);
    verify(h);

    // reassert a different role: no-op
    reset(h);
    replay(h);
    controller.reassertRole(h, HARole.STANDBY);
    verify(h);
  }

  /**
   * Start as SLAVE then set role to MASTER Tests normal role change transition. Check that
   * connected channels receive a setRole request
   */
  @Test
  public void testSetRole() throws Exception {
    doSetUp(HARole.STANDBY);
    RoleInfo info = controller.getRoleInfo();
    assertEquals(HARole.STANDBY, info.getRole());
    assertEquals(HARole.STANDBY, controller.getRole());

    OFSwitchHandshakeHandler h = createMock(OFSwitchHandshakeHandler.class);

    // Reassert the role.
    reset(h);
    h.sendRoleRequestIfNotPending(OFControllerRole.ROLE_SLAVE);
    replay(h);
    controller.reassertRole(h, HARole.STANDBY);
    verify(h);

    // reassert a different role: no-op
    reset(h);
    replay(h);
    controller.reassertRole(h, HARole.ACTIVE);
    verify(h);

    IHAListener listener = createMock(IHAListener.class);
    expect(listener.getName()).andReturn("foo").anyTimes();
    setupListenerOrdering(listener);
    listener.transitionToActive();
    expectLastCall().once();
    replay(listener);
    controller.addHAListener(listener);
    controller.setRole(HARole.ACTIVE, "FooBar");
    controller.processUpdateQueueForTesting();
    verify(listener);
    info = controller.getRoleInfo();
    assertEquals(HARole.ACTIVE, info.getRole());
    assertEquals("FooBar", info.getRoleChangeDescription());
    assertEquals(HARole.ACTIVE, controller.getRole());
  }

  /** Test other setRole cases: re-setting role to the current role, setting role to equal, etc. */
  @Test
  public void testSetRoleOthercases() throws Exception {
    doSetUp(HARole.STANDBY);

    // Create and add the HA listener
    IHAListener listener = createMock(IHAListener.class);
    expect(listener.getName()).andReturn("foo").anyTimes();
    setupListenerOrdering(listener);
    replay(listener);
    controller.addHAListener(listener);

    // Set role to slave again. Nothing should happen
    controller.setRole(HARole.STANDBY, "FooBar");
    controller.processUpdateQueueForTesting();
    verify(listener);

    reset(listener);
    expect(listener.getName()).andReturn("foo").anyTimes();
    listener.transitionToActive();
    expectLastCall().once();
    replay(listener);
  }

  @Test
  public void testSetRoleNPE() {
    try {
      controller.setRole(null, "");
      fail("Should have thrown an Exception");
    } catch (NullPointerException e) {
      // exptected
    }
    try {
      controller.setRole(HARole.ACTIVE, null);
      fail("Should have thrown an Exception");
    } catch (NullPointerException e) {
      // exptected
    }
  }
}