@Test
  public void basicTest() throws Exception {
    final Map<YangInstanceIdentifier, List<DOMRpcImplementation>> emptyImpls = new HashMap<>();
    final List<YangInstanceIdentifier> addList1 = new ArrayList<>();
    final List<YangInstanceIdentifier> addList2 = new ArrayList<>();
    final DOMRpcImplementation testClass = getTestRpcImplementation();
    final UnknownDOMRpcRoutingTableEntry test =
        new UnknownDOMRpcRoutingTableEntry(SchemaPath.ROOT, emptyImpls);

    TEST_LIST.add(testClass);
    emptyImpls.put(YangInstanceIdentifier.EMPTY, TEST_LIST);

    assertNotNull(test);
    assertNotNull(test.newInstance(emptyImpls));
    assertNotNull(test.invokeRpc(TEST_CONTAINER));
    assertNotNull(test.getImplementations());
    assertEquals(test.getImplementations(YangInstanceIdentifier.EMPTY), TEST_LIST);
    assertTrue(test.containsContext(YangInstanceIdentifier.EMPTY));
    assertTrue(test.registeredIdentifiers().contains(YangInstanceIdentifier.EMPTY));

    addList1.add(YangInstanceIdentifier.EMPTY);
    addList1.add(YangInstanceIdentifier.of(TestModel.TEST_QNAME));
    addList2.add(YangInstanceIdentifier.of(TestModel.TEST2_QNAME));

    final AbstractDOMRpcRoutingTableEntry tst = test.add(testClass, addList1);
    final AbstractDOMRpcRoutingTableEntry tst1 = tst.add(testClass, addList2);
    final AbstractDOMRpcRoutingTableEntry tst2 = tst1.remove(testClass, addList1);

    assertEquals(1, test.getImplementations().size());
    assertEquals(2, tst.getImplementations().size());
    assertEquals(3, tst1.getImplementations().size());
    assertNotNull(tst2.getImplementations());
    assertEquals(2, tst2.getImplementations().size());
  }
  /** Test case: NodeId translation */
  @Test
  public void testNodeId() {
    String logicalName = "node:1";
    UnderlayItem physicalNode =
        new UnderlayItem(
            mockNormalizedNode, null, TOPOLOGY_NAME, "node:1", CorrelationItemEnum.Node);
    OverlayItem logicalNode =
        new OverlayItem(Collections.singletonList(physicalNode), CorrelationItemEnum.Node);
    OverlayItemWrapper wrapper = new OverlayItemWrapper(logicalName, logicalNode);
    NormalizedNode<?, ?> normalizedNode = translator.translate(wrapper);

    NormalizedNode<?, ?> nodeId =
        NormalizedNodes.findNode(
                normalizedNode, YangInstanceIdentifier.of(TopologyQNames.NETWORK_NODE_ID_QNAME))
            .get();
    Assert.assertEquals(
        "NormalizedNode ID should be the same as the LogicalNodeWrapper ID",
        logicalName,
        nodeId.getValue());
  }
public abstract class AbstractDataChangeListenerTest {

  protected static final YangInstanceIdentifier TOP_LEVEL = YangInstanceIdentifier.of(Top.QNAME);
  private static final QName NAME_QNAME = QName.create(Top.QNAME, "name");
  protected static final String FOO = "foo";
  protected static final String BAR = "bar";
  protected static final String BAZ = "baz";

  private InMemoryDOMDataStore datastore;
  private SchemaContext schemaContext;
  private TestDCLExecutorService dclExecutorService;

  @Before
  public final void setup() throws Exception {
    YangModuleInfo moduleInfo = BindingReflections.getModuleInfo(TwoLevelList.class);
    ModuleInfoBackedContext context = ModuleInfoBackedContext.create();
    context.registerModuleInfo(moduleInfo);
    schemaContext = context.tryToCreateSchemaContext().get();

    dclExecutorService =
        new TestDCLExecutorService(SpecialExecutors.newBlockingBoundedFastThreadPool(1, 10, "DCL"));

    datastore = new InMemoryDOMDataStore("TEST", dclExecutorService);
    datastore.onGlobalContextUpdated(schemaContext);
  }

  @After
  public void tearDown() {
    if (dclExecutorService != null) {
      dclExecutorService.shutdownNow();
    }
  }

  /**
   * Create a new test task. The task will operate on the backed database, and will use the proper
   * background executor service.
   *
   * @return Test task initialized to clean up {@value #TOP_LEVEL} and its children.
   */
  public final DatastoreTestTask newTestTask() {
    return new DatastoreTestTask(datastore, dclExecutorService)
        .cleanup(DatastoreTestTask.simpleDelete(TOP_LEVEL));
  }

  public static final YangInstanceIdentifier path(final String topName, final String nestedName) {
    return path(topName)
        .node(NestedList.QNAME)
        .node(new NodeIdentifierWithPredicates(NestedList.QNAME, NAME_QNAME, nestedName));
  }

  public static final YangInstanceIdentifier path(final String topName) {
    return TOP_LEVEL
        .node(TopLevelList.QNAME)
        .node(new NodeIdentifierWithPredicates(TopLevelList.QNAME, NAME_QNAME, topName));
  }

  protected static DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> top() {
    return Builders.containerBuilder().withNodeIdentifier(new NodeIdentifier(Top.QNAME));
  }

  protected static void assertEmpty(final Collection<?> set) {
    Assert.assertTrue(set.isEmpty());
  }

  protected static void assertEmpty(final Map<?, ?> set) {
    Assert.assertTrue(set.isEmpty());
  }

  protected static <K> void assertContains(final Collection<K> set, final K... values) {
    for (K key : values) {
      Assert.assertTrue(set.contains(key));
    }
  }

  protected static <K> void assertNotContains(final Collection<K> set, final K... values) {
    for (K key : values) {
      Assert.assertFalse(set.contains(key));
    }
  }

  protected static <K> void assertContains(final Map<K, ?> map, final K... values) {
    for (K key : values) {
      Assert.assertTrue(map.containsKey(key));
    }
  }

  protected static <K> void assertNotContains(final Map<K, ?> map, final K... values) {
    for (K key : values) {
      Assert.assertFalse(map.containsKey(key));
    }
  }

  protected static CollectionNodeBuilder<MapEntryNode, MapNode> topLevelMap() {
    return ImmutableNodes.mapNodeBuilder(TopLevelList.QNAME);
  }

  protected static CollectionNodeBuilder<MapEntryNode, OrderedMapNode> nestedMap() {
    return Builders.orderedMapBuilder().withNodeIdentifier(new NodeIdentifier(NestedList.QNAME));
  }

  public static DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> topLevelList(
      final String key) {
    return ImmutableNodes.mapEntryBuilder(TopLevelList.QNAME, NAME_QNAME, key);
  }

  public static DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> nestedList(
      final String key) {
    return ImmutableNodes.mapEntryBuilder(NestedList.QNAME, NAME_QNAME, key);
  }

  public static final WriteTransactionCustomizer writeOneTopMultipleNested(
      final String topName, final String... nestedName) {
    CollectionNodeBuilder<MapEntryNode, OrderedMapNode> nestedMapBuilder = nestedMap();
    for (String nestedItem : nestedName) {
      nestedMapBuilder.addChild(nestedList(nestedItem).build());
    }

    final ContainerNode data =
        top()
            .addChild(
                topLevelMap()
                    .addChild(topLevelList(topName).addChild(nestedMapBuilder.build()).build())
                    .build())
            .build();

    return DatastoreTestTask.simpleWrite(TOP_LEVEL, data);
  }

  public static final WriteTransactionCustomizer deleteNested(
      final String topName, final String nestedName) {
    return DatastoreTestTask.simpleDelete(path(topName, nestedName));
  }
}